sergio777 opened this issue on Sep 18, 2021 ยท 13 posts
adp001 posted Sun, 19 September 2021 at 2:21 PM
Reworked the whole thing (rotation seems to work now) and splitted it into single functions that can be used independently (copy_trans(...), copy_rot(...), copy_scales(...), mirror_trans(...), mirror_rot(...)).
I also added a selection dialog.
from __future__ import print_function, division
try:
import poser
except ImportError:
# Not required while inside Poser Python, but very helpful for external editors.
# See https://adp.spdns.org?#FakePoser
from PoserLibs import POSER_FAKE as poser
import wx, sys
if sys.version_info.major > 2:
# Python 3 (Poser 12 and above)
basestring = str
SCENE = poser.Scene()
P_ROTS = poser.kParmCodeXROT, poser.kParmCodeYROT, poser.kParmCodeZROT
P_TRANS = poser.kParmCodeXTRAN, poser.kParmCodeYTRAN, poser.kParmCodeZTRAN
P_SCALES = poser.kParmCodeXSCALE, poser.kParmCodeYSCALE, poser.kParmCodeZSCALE, poser.kParmCodeASCALE
def copy_trans(source_obj, target_obj):
for code in P_TRANS:
target_obj.ParameterByCode(code).SetValue(source_obj.ParameterByCode(code).Value())
def copy_rot(source_obj, target_obj):
for code in P_ROTS:
target_obj.ParameterByCode(code).SetValue(source_obj.ParameterByCode(code).Value())
def copy_scales(source_obj, target_obj):
for code in P_SCALES:
target_obj.ParameterByCode(code).SetValue(source_obj.ParameterByCode(code).Value())
def mirror_trans(source_obj, target_obj, axis="XYZ", copyflag=False):
if isinstance(axis, basestring):
axis = [(ord(c) - ord("X")) for c in axis.upper()]
assert isinstance(axis, (list, tuple)), \
"Must be a string ('XYZ') or a list of integers (0, 1, 2)."
for idx, code in enumerate(P_TRANS):
if idx in axis:
target_obj.ParameterByCode(code).SetValue(-source_obj.ParameterByCode(code).Value())
elif copyflag:
target_obj.ParameterByCode(code).SetValue(source_obj.ParameterByCode(code).Value())
def mirror_rot(source_obj, target_obj, axis="XYZ", copyflag=False):
if isinstance(axis, basestring):
axis = [(ord(c) - ord("X")) for c in axis.upper()]
assert isinstance(axis, (list, tuple)), \
"Must be a string ('XYZ') or a list of integers (0, 1, 2)."
for idx, code in enumerate(P_ROTS):
if idx in axis:
p = source_obj.ParameterByCode(code)
v = p.Value() % 360
if v < 0:
v = 360 - v
if idx == 2: # Z rotation
target_obj.ParameterByCode(code).SetValue((180 - v) % 360)
else:
target_obj.ParameterByCode(code).SetValue((180 + v) % 360)
elif copyflag:
target_obj.ParameterByCode(code).SetValue(source_obj.ParameterByCode(code).Value())
def copy_light(obj, copyparms=True):
"""
Create a new light object and copy as many attributes as possible from
the old light to the new one. Attention: Maybe not all attributes are reachable
via Python!
"""
assert obj.IsLight()
new_light = SCENE.CreateLight()
for attr in dir(poser.ActorType):
if attr.startswith("Set") and any((_p in attr for _p in
("Ambient", "Light", "Display", "Atmosphere",
"Shading", "Shadow", "Visible", "RayTrace"))):
getattr(new_light, attr)(getattr(obj, attr[3:])())
# Attention: Don't use the above unfiltered! Your Poser may crash!
if copyparms:
# Copy objects parameters if required.
for new_parm in new_light.Parameters():
old_parm = obj.Parameter(new_parm.Name())
if not old_parm:
continue
for p in dir(poser.ParmType):
# Copy all attribute values of parameter we have a "Set.." function for.
if p.startswith("Set"):
# Try to get the value by shorten the attribute name
# (by removing "Set").
try:
value = getattr(old_parm, p[3:])()
# Because lights has a different parameter set
# than other parameters this may fail without consequences.
except poser.error:
pass
except AttributeError:
pass
else:
# Set the value.
getattr(new_parm, p)(value)
return new_light
def copy_mirrored_light(obj):
new_light = copy_light(obj, copyparms=True) # copyparms to get scales and position copied
mirror_trans(obj, new_light, axis="X")
mirror_rot(obj, new_light, axis="XYZ")
return new_light
#### A bit wxPython stuff ###
with wx.SingleChoiceDialog(None, message="Select a light to mirror", caption="Mirror Light",
choices=[o.Name() for o in SCENE.Lights()]) as dlg:
if dlg.ShowModal() == wx.ID_OK:
try:
light = SCENE.Actor(dlg.GetStringSelection())
except poser.error:
print("Selected light not available: '%s'" % dlg.GetStringSelection())
new_light = None
else:
new_light = copy_mirrored_light(light)