Forum Moderators: Staff
Poser Python Scripting F.A.Q (Last Updated: 2024 Dec 02 3:16 pm)
it seems that you can only mirror the parameters if you mirror them separately. and don't forget to scene.Draw() or scene.DrawAll() at the end.
```
if transitions().IsYRotate( parm ):
parm.SetValue( -parm.Value() )
if transitions().IsXTranslate( parm ):
parm.SetValue( -parm.Value() )
```
and the forum appears to be borked again.
Locked Out
Thanks for your answer Structure, the code works fine as long as the light parameter Zrot is 0, in cases where Z rotatation is different from zero the results are wrong.
There should be some way to translate any light position to one where the Zrot parameter is 0 and then run the script, but I haven't figured out how to do it.
from __future__ import print_function, division
import 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
def copy_light(obj):
"""
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:])())
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, trans="XYZ", rot="XYZ"):
if isinstance(trans, basestring):
trans = [(ord(c) - ord("X")) for c in trans.upper()]
assert isinstance(trans, (list, tuple))
if isinstance(rot, basestring):
rot = [(ord(c) - ord("X")) for c in rot.upper()]
assert isinstance(rot, (list, tuple))
new_light = copy_light(obj)
for idx, code in enumerate(P_TRANS):
if idx in trans:
p = new_light.ParameterByCode(code)
p.SetValue(-p.Value())
for idx, code in enumerate(P_ROTS):
if idx in rot:
p = new_light.ParameterByCode(code)
v = p.Value() % 360
p.SetValue(180-v)
return new_light
light = copy_mirrored_light(SCENE.Actor("Light 1"), trans="X", rot="XYZ")
The above function "copy_mirrored_light" takes an existing light and creates a mirrored copy of it. Parameter "trans" is a string containing the translation axis to mirror (X, Y and Z in one string, like "XYZ"). The same for "rot", the rotation axis. The last line above shows the most typical parameters: trans="X" and rot="XYZ".
Instead of a string a tuple or list with up to 3 values (0=="X", 1=="Y", 2=="Z") is also fine.
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)
Pretty much anything can be made into a light using emitters.
As I wrote in the source as a comment: Poser Python does not allow access to everything. Or only in a very cumbersome way.
So there is nothing else than manual work (and the hope that there will be a corresponding function in Poser Python someday):
Use the menu item "Copy Object" in Poser to get a 1:1 copy. And then apply the mirror functions (that's the reason why I split this into single functions).
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.
I can move a light manually easily but sometimes it's not so accurate, so I tried to make a script to mirror a light by changing the sign of the Yrotation or/and Trans values, but it didn't work. Does anyone have any idea how to do it?