adp001 opened this issue on Apr 06, 2021 ยท 3 posts
adp001 posted Tue, 06 April 2021 at 4:36 AM
For a special case I needed a script able to clean a morph if that morph touches a certain material. So I made one (not very well tested, but it seems to work):
from __future__ import division, print_function
try:
import poser
except ImportError:
from PoserLibs import POSER_FAKE as poser
import sys, wx
if sys.version_info.major > 2:
# Python 3 (Poser 12 and above)
basestring = str
from importlib import reload
map = lambda a, b: [a(_b) for _b in b]
newIdRef = wx.NewIdRef
else:
# Python 2 (Poser 11 and below)
newIdRef = wx.NewId
def find_polys(polys, materialindexlist):
"""Find and return polygons with material index contained in materialindexlist."""
poly_indices = list()
for idx, poly in enumerate(polys): # type: (int, poser.PolygonType)
if poly.MaterialIndex() in materialindexlist:
poly_indices.append(idx)
return poly_indices
def verts_from_polys(geom, polyindices):
"""Find and return vertices contained in polygons."""
assert isinstance(geom, poser.GeomType)
assert isinstance(polyindices, list)
vertexindices = list()
sets = geom.Sets()
polys = geom.Polygons()
for polyidx in polyindices:
p = polys[polyidx] # type: poser.PolygonType
vertexindices.extend(sets[p.Start():p.Start()+p.NumVertices()])
return vertexindices
def reset_morphs_in_material(figure, materiallist, morphlist=None):
assert isinstance(figure, poser.FigureType)
if isinstance(materiallist, basestring):
materiallist = [materiallist, ]
if isinstance(morphlist, basestring):
morphlist = [morphlist, ]
assert hasattr(materiallist, "__iter__")
assert hasattr(morphlist, "__iter__")
# Make a list of materialnames from figure.
figure_matnames = [m.Name() for m in figure.Materials()]
# Convert all materials in materiallist to index positions.
# materiallist must contain strings or poser.Material objects.
try:
materiallist = [figure_matnames.index(m if isinstance(m, basestring) else m.Name())
for m in materiallist]
except AttributeError:
print("One or more materials is not string or ")
return None
except IndexError:
print("One or more Materialnames could not be found.")
return None
for ac in [_ac for _ac in figure.Actors() if _ac.IsBodyPart()]: # type: poser.ActorType
if hasattr(ac, "Geometry"):
geom = ac.Geometry()
if not geom or geom.NumVertices() == 0:
continue
vertex_indices = verts_from_polys(geom, find_polys(geom.Polygons(), materiallist))
if len(vertex_indices) != 0:
for morph in [p for p in ac.Parameters() if p.IsMorphTarget()]: # type: poser.ParmType
if morphlist is not None and morph not in morphlist:
continue
if morph.NumMorphTargetDeltas() != 0:
cnt = 0
for idx in range(geom.NumVertices()):
v = morph.MorphTargetDelta(idx)
if v[0] != 0 or v[1] != 0 or v[2] != 0:
if idx in vertex_indices:
cnt += 1
morph.SetMorphTargetDelta(idx, 0, 0, 0)
if cnt:
print(cnt, "morph vertices in", ac.Name(), ">", morph.Name())
Usage:
reset_morphs_in_material(figure, materiallist, morphlist)
"morphlist" is a list of morphnames or None. In case of None all morphs are used.
"materiallist" is a list of materialnames or poser.Materials(). Vertices contained in a morph and covered by one of the named materials are set to 0.
I used this to clean up morphs for hair with a lot of materialgroups. And for cloth to clean "buttons". It's faster and easier as using the morphbrush :)
an0malaus posted Thu, 08 April 2021 at 10:33 AM
Nice! :-)
Verbosity: Profusely promulgating Graham's number epics of complete and utter verbiage by the metric monkey barrel.
adp001 posted Thu, 08 April 2021 at 11:07 AM
Thanks. But it wont work with a morphlist, because I forgot ".Name()" after "morph" :)
Here is a working version:
from __future__ import division, print_function
try:
import poser
except ImportError:
from PoserLibs import POSER_FAKE as poser
import sys, wx
if sys.version_info.major > 2:
# Python 3 (Poser 12 and above)
basestring = str
from importlib import reload
map = lambda a, b: [a(_b) for _b in b]
newIdRef = wx.NewIdRef
else:
# Python 2 (Poser 11 and below)
newIdRef = wx.NewId
def find_polys(polys, materialindexlist):
"""Find and return polygons with material index contained in materialindexlist."""
poly_indices = list()
for idx, poly in enumerate(polys): # type: (int, poser.PolygonType)
if poly.MaterialIndex() in materialindexlist:
poly_indices.append(idx)
return poly_indices
def verts_from_polys(geom, polyindices):
"""Find and return vertices contained in polygons."""
assert isinstance(geom, poser.GeomType)
assert isinstance(polyindices, list)
vertexindices = list()
sets = geom.Sets()
polys = geom.Polygons()
for polyidx in polyindices:
p = polys[polyidx] # type: poser.PolygonType
vertexindices.extend(sets[p.Start():p.Start()+p.NumVertices()])
return vertexindices
def reset_morphs_in_material(figure, materiallist, morphlist=None):
assert isinstance(figure, poser.FigureType)
if isinstance(materiallist, basestring):
materiallist = [materiallist, ]
if isinstance(morphlist, basestring):
morphlist = [morphlist, ]
assert hasattr(materiallist, "__iter__")
assert hasattr(morphlist, "__iter__")
# Make a list of materialnames from figure.
figure_matnames = [m.Name() for m in figure.Materials()]
# Convert all materials in materiallist to index positions.
# materiallist must contain strings or poser.Material objects.
try:
materiallist = [figure_matnames.index(m if isinstance(m, basestring) else m.Name())
for m in materiallist]
except AttributeError:
print("One or more materials is not string or ")
return None
except IndexError:
print("One or more Materialnames could not be found.")
return None
for ac in [_ac for _ac in figure.Actors() if _ac.IsBodyPart()]: # type: poser.ActorType
if hasattr(ac, "Geometry"):
geom = ac.Geometry()
if not geom or geom.NumVertices() == 0:
continue
vertex_indices = verts_from_polys(geom, find_polys(geom.Polygons(), materiallist))
if len(vertex_indices) != 0:
for morph in [p for p in ac.Parameters() if p.IsMorphTarget()]: # type: poser.ParmType
if morphlist is not None and morph.Name() not in morphlist:
continue
if morph.NumMorphTargetDeltas() != 0:
cnt = 0
for idx in range(geom.NumVertices()):
v = morph.MorphTargetDelta(idx)
if v[0] != 0 or v[1] != 0 or v[2] != 0:
if idx in vertex_indices:
cnt += 1
morph.SetMorphTargetDelta(idx, 0, 0, 0)
if cnt:
print(cnt, "morph vertices in", ac.Name(), ">", morph.Name())