Sat, Nov 9, 6:27 PM CST

Renderosity Forums / Poser Python Scripting



Welcome to the Poser Python Scripting Forum

Forum Moderators: Staff

Poser Python Scripting F.A.Q (Last Updated: 2024 Sep 18 2:50 am)

We now have a ProPack Section in the Poser FreeStuff.
Check out the new Poser Python Wish List thread. If you have an idea for a script, jot it down and maybe someone can write it. If you're looking to write a script, check out this thread for useful suggestions.

Also, check out the official Python site for interpreters, sample code, applications, cool links and debuggers. This is THE central site for Python.

You can now attach text files to your posts to pass around scripts. Just attach the script as a txt file like you would a jpg or gif. Since the forum will use a random name for the file in the link, you should give instructions on what the file name should be and where to install it. Its a good idea to usually put that info right in the script file as well.

Checkout the Renderosity MarketPlace - Your source for digital art content!



Subject: Is there any way to know if a figure is hair?


maur_2005 ( ) posted Wed, 13 October 2021 at 10:26 PM · edited Sat, 09 November 2024 at 6:18 PM

I am making a script that hides the hair of the figures and I was thinking, how can I know if a figure is hair? Some hairs have the word "Hair" in their names but some don't, so how can I make something more generic?

for fig in scene.figures():
   name=fig.Name().lower()
   if name.find("hair")
      fig.SetVisible(0)






structure ( ) posted Thu, 14 October 2021 at 1:08 AM · edited Fri, 15 October 2021 at 11:41 PM
Forum Coordinator

There is a function called IsHairProp() ( only works with hr2 (prop) hair ) I never found it to be reliable.

You could check it's name or actor names and / materials for certain things.
sadly because there is no recognised naming convention, most modellers
use a variety of names. so searching for cap or skull in actors / materials
may not work, and as you noted searching for "hair" in the name may also not work.

Seemingly, no 2 people use the same naming convention.
Some modellers don't even use the same conventions for all of their models.

*edit*

you could check it's parent or what it is conformed to.:

For figures, check the conform target :

    if figure.ParentActor().Name() == "Head": for props check the parent:
    if actor.Parent().Name() == "Head":

if the parent / conform target is "Head", it is likely ( not 100% foolproof ) that it is hair. 
( make something foolproof, they will make a better fool.)

Locked Out


HartyBart ( ) posted Thu, 14 October 2021 at 5:15 AM

The following might lead you. Eguchi showed how to find target 'eye, not brow' in the current children parts of the head. By excluding those that are not hair, presumably one would be left with the hair, without actually having to name it.

if figure:
    head_parts = figure.Actor("Head").Children()
    for target in head_parts:
        targetname = target.InternalName()
        if "Brow" not in targetname and ("Eye" in targetname or "eye" in targetname) :
            [then do something]



Learn the Secrets of Poser 11 and Line-art Filters.


HartyBart ( ) posted Thu, 14 October 2021 at 5:17 AM

Yay! Copy and paste from a code editor now works!



Learn the Secrets of Poser 11 and Line-art Filters.


structure ( ) posted Thu, 14 October 2021 at 7:09 AM
Forum Coordinator
HartyBart posted at 5:15 AM Thu, 14 October 2021 - #4428909
if figure:
    head_parts = figure.Actor("Head").Children()
    for target in head_parts:
        targetname = target.InternalName()
        if "Brow" not in targetname and ("Eye" in targetname or "eye" in targetname) :
            [then do something]
You may need to edit this code since some hairs contain a part called brow, or has the word brow in it. 

Locked Out


Bastep ( ) posted Thu, 14 October 2021 at 10:27 PM

Hi, I have had a similar problem. My solution, just add the word hair in the name of the hair object. It is annoying, but actually only a small additional effort. Your Python program will always work 100% from now on.

Greetings



structure ( ) posted Fri, 15 October 2021 at 6:25 AM · edited Fri, 15 October 2021 at 8:26 AM
Forum Coordinator
Bastep posted at 10:27 PM Thu, 14 October 2021 - #4428951

Hi, I have had a similar problem. My solution, just add the word hair in the name of the hair object. It is annoying, but actually only a small additional effort. Your Python program will always work 100% from now on.

Greetings

This is a perfectly good solution if it is for personal use, however if the script is meant for distribution this approach will not work/is not optimal. 

Locked Out


structure ( ) posted Fri, 15 October 2021 at 7:33 AM · edited Fri, 15 October 2021 at 8:34 AM
Forum Coordinator
class haircontrols:
    def isithair( self, item ):
badnames = (
"eye", "tongue", "teeth", "hat", "mask", "veil" ) return True if not any(badname in item.InternalName().casefold() for badname in badnames) else False
you can expand the badnames to include anything else that you find in other 
objects that you would not normally find in a hair object.
This is untested but it should work, perhaps with a little 
modification.

Locked Out


HartyBart ( ) posted Fri, 15 October 2021 at 10:34 AM

Thanks structure. This leads me to ask: is it possible to change or append the InternalName or is it fixed forever?  I was just idly wondering if a process could quickly work through all "Hair" items in the user's personal Library, and tag them with something that could then connect with a Python script when used. A tag-name such as "Hairy", for instance.



Learn the Secrets of Poser 11 and Line-art Filters.


structure ( ) posted Fri, 15 October 2021 at 3:02 PM · edited Fri, 15 October 2021 at 3:06 PM
Forum Coordinator

afaik, it is not possible to change the internal name. However, you could change the external name with a script, combing through the folder would work with hr2 files but not with pp2 or cr2 unless there is an obvious way to tell them apart from a coat or a hat.

Or you could write a script which could ask the user for each item it finds whether it  is hair or not. 
my approach would be to build a user editable database. 

import os
import poser
import wx

extensions = ( ".hr2", ".hrz" )
prefslocation = poser.PrefsLocation()
dbfile = os.path.join( prefslocation, "hairdb", "hairdb.txt" )
if not os.path.exists( os.path.dirname( dbfile ) ):
    os.makedirs( os.path.dirname( dbfile ) )
    with open( dbfile, "w" ) as writefile:
        writefile.write("")

# create hair database
libraries = poser.Libraries()
for library in libraries:
    hairlibrary = os.path.join( library, "Runtime", "Library", "Hair" )
    for root, folders, files in os.walk( hairlibrary ):
        for file in files:
            if file.endswith( extensions ):
                file = os.path.join( root, file )
                with open( file, "r" ) as readfile:
                    lines = readfile.readlines()
                for line in lines:
                    if line.startswith( "   name" ):
                        line = line.strip()
                        line = line.replace( "name".casefold(), "" )
                        break
                with open( file, "a" ) as appendfile:
                    appendfile.write( line + "\n" )


This way, you can then write a script which accesses the database to see if any object in the scene is a recognised hair. 
Obviously any hair pp2 or cr2 would likely need to be added manually or with a combing script that allows the user to select which objects are hair and which are not. 

Locked Out


structure ( ) posted Sat, 16 October 2021 at 12:27 AM · edited Sat, 16 October 2021 at 1:10 AM
Forum Coordinator

so after some experimentation - it seems that the ParentActor of a figure is always the "Body" actor.

This script finds most hairs, but also counts things like the woodgoddess hood as a hair ( it has a material called skullcap )
with some modification ( bearing in mind your personal needs ) it could be made to ignore hoods caps veils etc.

from pathlib import Path
import poser
import wx

scene = poser.Scene()
letsdebug = False

def isvalid( actor , bodypart=False ): # a modified function of a Snarlygribbly routine
    if not actor is None:
        n       =   actor.Name().lower()
        if n.endswith("con") or n.endswith("con 1"):
            return False
        data    =   [
                    'atmosphere','background','bodymorphs','centerofmass',
                    'faceroom','focusdistancecontrol','ground','grouping',
                    'universe'
                    ]
        for d in data:
            if d in n:
                return False
        if actor.IsZone() or actor.IsBase() or actor.IsDeformer():
            return False
        if actor.IsLight() or actor.IsCamera():
            return False
        if actor.IsProp() or ( actor.IsBodyPart() and bodypart == True ):
            return True
    return False

def get_geometry( item ):
    geomName = item.GeomFileName()
   
    if (geomName and not geomName == ""):
        geom = Path( geomName ).stem
        geompath = Path( geomName ).parent.resolve()
   
    return geom, geompath

def get_parent( item, parent = None ):

    if item.IsFigure():
        try:
            parent = item.ParentActor()
        except:
            parent = None
    if item.IsProp():
        try:
            parent = actor.Parent()
        except:
            parent = None
       
    if letsdebug:
        try:
            print( f"{item.Name()}\n\t{parent.Name()}\t{isithair( item )}" )
        except:
            pass

    if parent:
        if parent.Name() == "Head" or parent.Name() == "Body":
            return isithair( item, parent )

    else:
        return False

def isithair( item, parent = None ):
    # set up list of valid materials
    validmats = ( "bangs", "skullcap", "hair" )
    # validnames = ( "hair", "hr" )
    # set case independent names
    itemname = item.Name().casefold()
    parentname = parent.Name().casefold()
    # check itemname and materials before relying on parent
   
    if "hair" in itemname or itemname.startswith("hr"):
        return True
   
    if item.IsFigure():
        for material in item.Materials():
            if any( mat in material.Name() for mat in validmats ):
                return True

    if not parentname == "head" and not parentname == "Body":
        return False
    badnames = ("eye", "tongue", "teeth", "hat", "mask", "veil" )
    try:
        for actor in figure.Actors():
            targetname = actor.InternalName().casefold()
            return True if not any(badname in targetname\
                for badname in badnames) else False
    except:
        if letsdebug:
            print( item )
        targetname = item.InternalName().casefold()
        return True if not any(badname in targetname\
                for badname in badnames) else False

for figure in scene.Figures():
    hair = get_parent( figure )
    if hair:
        print(f"{get_geometry( figure )[0]}\n\t{get_geometry( figure )[1]}")
        if letsdebug:
            print ( figure.Name(), hair, figure.ParentActor().Name() )

for actor in scene.Actors():
    hair = get_parent( actor )
    if hair and isvalid( actor ):
        print(f"{get_geometry( actor )[0]}\n\t{get_geometry( actor )[1]}")
        if letsdebug:
            print ( actor.Name(), hair, actor.Parent().Name() )

Output :
bl_RebyHair X:\Poser12\Runtime\Geometries\DAZHair\Victoria4 FoxHair V4 X:\Poser12\Runtime\Geometries\Arki\FoxHair aprilyshZed X:\Poser12\Runtime\Geometries\AprilYSH\AprilHair LLF-BastHairV4 X:\Poser12\Runtime\Geometries\Littlefox\BastV4 Genie Hair2 X:\Poser12\Runtime\Geometries\! DD_KJ\Genie hair BandanaHair X:\Poser12\Runtime\Geometries\P3DArt\CarGirlV4 p3dFWHair X:\Poser12\Runtime\Geometries\Pretty3D\FWHair pl_hair_v4 X:\Poser12\Runtime\Geometries\Pretty3D\PrettyLongHair SW_MintaHR01 X:\Poser12\Runtime\Geometries\SWAM_Art\2015_MintaHR SW_Yunko01 X:\Poser12\Runtime\Geometries\SWAM_Art\2013_YunkoHR XtremePonytail X:\Poser12\Runtime\Geometries\DIGIpixel\PAXtreme

Locked Out


adp001 ( ) posted Mon, 18 October 2021 at 1:32 PM
structure posted at 12:27 AM Sat, 16 October 2021 - #4428982

so after some experimentation - it seems that the ParentActor of a figure is always the "Body" actor.


Use figure.RootActor(). It's made for this :)




structure ( ) posted Tue, 19 October 2021 at 5:36 AM
Forum Coordinator
adp001 posted at 1:32 PM Mon, 18 October 2021 - #4429062
structure posted at 12:27 AM Sat, 16 October 2021 - #4428982

so after some experimentation - it seems that the ParentActor of a figure is always the "Body" actor.


Use figure.RootActor(). It's made for this :)

Thanks ADP

Locked Out


structure ( ) posted Tue, 26 October 2021 at 8:05 PM · edited Wed, 27 October 2021 at 2:44 AM
Forum Coordinator

adp001 posted at 1:32 PM Mon, 18 October 2021 - #4429062

structure posted at 12:27 AM Sat, 16 October 2021 - #4428982

so after some experimentation - it seems that the ParentActor of a figure is always the "Body" actor.


Use figure.RootActor(). It's made for this :)

import poser

scene = poser.Scene()
figures = scene.Figures()

for figure in figures:
    print(figure.Name(), figure.RootActor().Name())


output :

Victoria4 Body
Hair Body

Locked Out


Privacy Notice

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.