Wed, Nov 20, 10:29 AM 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: Script for setting U/V_Scale of image maps in current figure/actor (nearly done)


3dcheapskate ( ) posted Thu, 01 March 2012 at 2:51 AM · edited Wed, 20 November 2024 at 10:28 AM

Okay, here's my first stab at the script. I adopted the monolithic one-size-fits-all approach. It uses one AskMenu() and makes copious use of the DialogSimple MessageBox() and YesNo() methods to give a reasonable amount of flexibility. Here's an overview of what it does:

If you have a figure selected it asks if you want to change all the materials in that figure.
If not (or you say no), and you have an actor selected it asks if you want to change all materials in that actor.
If not (or you say no), and you have a material selected it asks if you want to change that material.

If it has got a material list, then it asks if you want to set a fixed tiling value, or adjust the current value by a percentage.
It asks for confirmation if you enter values that are likely to be mistakes.
It then states what it's about to do, and asks for confirmation.

If there's more than one material it gives you the option to select yes/no to each material individually.

Here's the main code (functions GetTilingPercent() and GetTilingPercent() in the following posts).

Any advice, suggestions, and constructive criticism much appreciated:

import poser  
  
# function defs here  
          
try:  
  True, False  
except NameError:  
  (True, False) = (1, 0)  
   
aborted = False  
fig = poser.Scene().CurrentFigure()  
act = poser.Scene().CurrentActor()  
mat = poser.Scene().CurrentMaterial()  
if fig:  
    yn = poser.DialogSimple.YesNo(" Current Figure: "+str(fig.Name())+"nnChange all materials for this figure?")  
    if yn == 0:  
        fig = None  
    else:  
        mats = fig.Materials()  
if act and not fig:  
    yn = poser.DialogSimple.YesNo(" Current Actor: "+str(act.Name())+"nnChange all materials for this actor?")  
    if yn == 0:  
        act = None  
    else:  
        mats = act.Materials()  
if mat and not act:  
    yn = poser.DialogSimple.YesNo(" Current Material: "+str(mat.Name())+"nnChange this material?")  
    if yn == 0:  
        act = None  
    else:  
        mats = [mat]  
if not mat:  
    poser.DialogSimple.MessageBox("Please select a figure, actor, or material first!")  
  
if mats:  
    optlist = ("Adjust tiling by xxx%","Set tiling to xxx")  
    action = poser.DialogSimple.AskMenu("Change Tiling (U/V_Scale)","Method?",optlist)  
    if action == optlist[0]:  
        tp = GetTilingPercent()  
        yn = poser.DialogSimple.YesNo("U_Scale and V_Scale will be set to "+str(tp)+"% of their current values.nnYes to proceed, No to cancel")  
        if yn == 0:  
            poser.DialogSimple.MessageBox("Operation cancelled.")  
            aborted = True  
        else:  
            bypc = True  
    elif action == optlist[1]:  
        tv = GetTilingValue()  
        yn = poser.DialogSimple.YesNo("U_Scale and V_Scale will be set to "+str(tv)+".nnYes to proceed, No to cancel")  
        if yn == 0:  
            poser.DialogSimple.MessageBox("Operation cancelled.")  
            aborted = True  
        else:  
            bypc = False  
    else:  
        poser.DialogSimple.MessageBox("Operation cancelled.")  
        aborted = True  
    if not aborted:  
        interactive = False  
        cnt = 0  
        yn = poser.DialogSimple.YesNo("There are "+str(len(mats))+" materials.nWould you like to confirm each material individually?")  
        if yn != 0:  
            interactive = True  
        for mat in mats:  
            cnt = cnt+1  
            changemat = True  
            if interactive:  
                yn = poser.DialogSimple.YesNo("Material: "+mat.Name()+"n(Material "+str(cnt)+" of "+str(len(mats))+")nnChange this material?")  
                if yn == 0:  
                    changemat = False  
            if changemat:  
                tree = mat.ShaderTree()  
                nods = tree.Nodes()  
                for nod in nods:  
                    if nod.Type() == poser.kNodeTypeCodeIMAGEMAP:  
                        if bypc:  
                            nv = nod.Input(2).Value() * tp / 100.0    
                            nod.Input(2).SetFloat(nv)  
                            nv = nod.Input(3).Value() * tp / 100.0  
                            nod.Input(3).SetFloat(nv)  
                        else:  
                            nod.Input(2).SetFloat(tv)  
                            nod.Input(3).SetFloat(tv)  
                tree.UpdatePreview()  

Like I said - any advice, suggestions, and constructive criticism much appreciated.


The 3Dcheapskate* occasionally posts sensible stuff. Usually by accident.
And it usually uses Poser 11, with units set to inches. Except when it's using Poser 6 or PP2014, or when its units are set to PNU.

*also available in ShareCG, DAZ, and HiveWire3D flavours (the DeviantArt and CGBytes flavour have been discontinued).



3dcheapskate ( ) posted Thu, 01 March 2012 at 2:51 AM · edited Fri, 04 September 2015 at 10:18 PM

def GetTilingPercent():
    global aborted
    tp = poser.DialogSimple.AskInt("Enter the percentage you want to scale by.n(Integer values only, no % sign)")
    if tp is None:
        poser.DialogSimple.MessageBox("Invalid entry (or user cancelled)nnOperation cancelled.")    
        aborted = True
        return 0
    if tp == 0:
        yn = poser.DialogSimple.YesNo("Zero will turn off tiling?nnDid you intend to do this?")
        if yn == 0:
            poser.DialogSimple.MessageBox("Operation cancelled.")
            aborted = True
            return 0
        else:
            return 0
    if tp == 100:
        poser.DialogSimple.MessageBox("A value of 100% will have no effect.n(makes the tiles exactly the same size)nnOperation cancelled.")
        aborted = True
        return 0
    if tp         yn = poser.DialogSimple.YesNo("Negative values ("+str(tp) + "%) invert the texture.nnDid you intend to do this?")
        if yn == 0:
            poser.DialogSimple.MessageBox("Ignoring the minus sign.n Proceeding with "+str(-tp) + "%")
            tp = -tp
    if tp > 1000 or tp         yn = poser.DialogSimple.YesNo(str(tp)+"% will make the tiles "+str(tp/100)+" times bigger.nnDid you intend to do this?")
        if yn == 0:
            poser.DialogSimple.MessageBox("Operation cancelled.")
            aborted = True
            return 0
    elif (tp   0) or (tp >-10 and tp         yn = poser.DialogSimple.YesNo(str(tp)+"% will make the tiles "+str(100/tp)+" times smaller?.nnDid you intend to do this?")
        if yn == 0:
            poser.DialogSimple.MessageBox("Operation cancelled.")
            aborted = True
            return 0
    else:
        return tp


The 3Dcheapskate* occasionally posts sensible stuff. Usually by accident.
And it usually uses Poser 11, with units set to inches. Except when it's using Poser 6 or PP2014, or when its units are set to PNU.

*also available in ShareCG, DAZ, and HiveWire3D flavours (the DeviantArt and CGBytes flavour have been discontinued).



3dcheapskate ( ) posted Thu, 01 March 2012 at 2:52 AM · edited Sat, 05 September 2015 at 12:10 AM

def GetTilingValue():
    global aborted
    tv = poser.DialogSimple.AskFloat("Enter the tiling value to set.n(Numeric values only)")
    if tv is None:
        poser.DialogSimple.MessageBox("Invalid entry (or user cancelled)nnOperation cancelled.")    
        aborted = True
        return 0.0
    if tv == 0.0:
        yn = poser.DialogSimple.YesNo("Zero will turn off tiling?nnDid you intend to do this?")
        if yn == 0:
            poser.DialogSimple.MessageBox("Operation cancelled.")
            aborted = True
            return 0.0
        else:
            return 0.0
    if tv         yn = poser.DialogSimple.YesNo("Negative values ("+str(tv) + "%) invert the texture.nnDid you intend to do this?")
        if yn == 0:
            poser.DialogSimple.MessageBox("Ignoring the minus sign.n Proceeding with "+str(-tv) + "%")
            tv = -tv
    if tv > 100.0 or tv         yn = poser.DialogSimple.YesNo(str(tv)+"% will make the tiles "+str(tv/100)+" times bigger.nnDid you intend to do this?")
        if yn == 0:
            poser.DialogSimple.MessageBox("Operation cancelled.")
            aborted = True
            return 0.0
    elif (tv   0) or (tv >-0.01 and tv         yn = poser.DialogSimple.YesNo(str(tv)+"% will make the tiles "+str(100/tv)+" times smaller?.nnDid you intend to do this?")
        if yn == 0:
            poser.DialogSimple.MessageBox("Operation cancelled.")
            aborted = True
            return 0.0
    else:
        return tv


The 3Dcheapskate* occasionally posts sensible stuff. Usually by accident.
And it usually uses Poser 11, with units set to inches. Except when it's using Poser 6 or PP2014, or when its units are set to PNU.

*also available in ShareCG, DAZ, and HiveWire3D flavours (the DeviantArt and CGBytes flavour have been discontinued).



3dcheapskate ( ) posted Thu, 01 March 2012 at 2:54 AM · edited Thu, 01 March 2012 at 2:57 AM

Hmmm... not sure that was the best way to post it, with all the line-wrapping. Maybe I should have done it as an attachment?

Anyway, as I said earlier, any advice, suggestions, and constructive criticism much appreciated.


The 3Dcheapskate* occasionally posts sensible stuff. Usually by accident.
And it usually uses Poser 11, with units set to inches. Except when it's using Poser 6 or PP2014, or when its units are set to PNU.

*also available in ShareCG, DAZ, and HiveWire3D flavours (the DeviantArt and CGBytes flavour have been discontinued).



ElZagna ( ) posted Thu, 01 March 2012 at 5:58 AM

Well, here's my suggestion, and it's the same suggestion I offer to almost every Poser script out there. Tell us what its purpose is. You've told us what it does - it sets the U/V_Scale of image maps in the current figure/actor -  but that's a different thing from what its purpose is. What problem does it solve? In MBA parlance, what pain does it address? Why would someone want to use it?

There was an old Saturday Night Live skit that started with, "How many times have you coughed up a piece of lung and had no place to store it?" (It was a commercial for Playmate coolers.) A silly example, I guess, but that's how products are sold. You don't sell coolers by saying, "Playmate coolers insulate their contents by surrounding it with materials that don't allow the heat exchange... " You start with some kind of "don't you hate it when" statement.

I know I'm going on and on about this, but I see so many scripts out there that someone has put hours and hours into, but they never get used because the potential users have no clue as to why they would want to use them. 

Sorry I can't be more helpful about the script per se. It looks impressive, though.



OS: Windows 10 64-bit, Poser: 10


3dcheapskate ( ) posted Thu, 01 March 2012 at 7:23 AM · edited Thu, 01 March 2012 at 7:37 AM

Very sensible advice. Thanks. I think we get so involved in what we're doing that we forget the obvious. So here's what I should have said at the top:

This script makes it much easier to adjust the size of my tileable mail textures (in the Renderosity Freestuff here) to suit the item it's applied to. It should also be suitable for adjusting any texture that uses a tiled image map. Or to follow on from that Saturday Night Live sketch - "Don't you just hate it when that ballista bolt goes straight through the holes in your chain mail? You should have been using smaller links - if only you'd had this handy little Tile-O-Matic script!"

I had been trying to do this with a Poser 5 material file, but advice in this thread pointed me to Python, and once I'd got the script more-or-less ready I moved to this thread you're looking at (but forgot to point back to the original thread).

It's my first ever Python script, which is the main reason I've asked for comments. I'm still debugging it, but I posted it since it seems to work 99% as intended (testing in Poser 6 on Windows 7).


The 3Dcheapskate* occasionally posts sensible stuff. Usually by accident.
And it usually uses Poser 11, with units set to inches. Except when it's using Poser 6 or PP2014, or when its units are set to PNU.

*also available in ShareCG, DAZ, and HiveWire3D flavours (the DeviantArt and CGBytes flavour have been discontinued).



ElZagna ( ) posted Thu, 01 March 2012 at 9:11 AM

You got it! I see that you're obviously no stranger to the concept. From your "Miscellaneous Positional Reset Poses"

Do you ever make a complete mess of posing a figure, and need to start again?
Do you have to spend ages hunting around for a pose to reset the figure?
Simple solution - put all your figure reset poses in one easy-to-locate folder!



OS: Windows 10 64-bit, Poser: 10


ElZagna ( ) posted Thu, 01 March 2012 at 9:23 AM

Another thing I like about your comments for your Reset Poses script is that you address the issue of obsolescence. It would be nice if all scripts indicated if subsequent releases of Poser had made the script obsolete. I spent a lot of time once trying to get a script to work, and finally asked the author what I was doing wrong. He said, “That old thing? Forget it. Poser does that natively now.”



OS: Windows 10 64-bit, Poser: 10


3dcheapskate ( ) posted Fri, 02 March 2012 at 12:06 PM · edited Fri, 02 March 2012 at 12:07 PM

Actually the "Miscellaneous Positional Reset Poses"  are just that, .pz2 pose files. But your comments are just as valid nevertheless.

I'm going to upload the script to the Renderosity Freestuff as soon as I'm happy with it - I'm not sure how long to wait to see if anybody comments on the script itself.  I've already fixed a couple of bugs, but one I'm not sure how to handle - the line...

mats = act.Materials()

...(around the 22nd code line in the first post) errors if you have, say, just a camera in the scene as the selected actor. I could use an

if not act.IsCamera():

but I wonder what other actors will cause similar problems?


The 3Dcheapskate* occasionally posts sensible stuff. Usually by accident.
And it usually uses Poser 11, with units set to inches. Except when it's using Poser 6 or PP2014, or when its units are set to PNU.

*also available in ShareCG, DAZ, and HiveWire3D flavours (the DeviantArt and CGBytes flavour have been discontinued).



markschum ( ) posted Fri, 02 March 2012 at 10:40 PM

you can do an

if mats:

    # do stuff

that will skip if the actor has no materials.


3dcheapskate ( ) posted Sat, 03 March 2012 at 4:51 AM · edited Sat, 03 March 2012 at 4:52 AM

It's an odd one, cos I already use an 'if mats:'. I stuck a message box either side of it like this.

poser.DialogSimple.MessageBox("Gonna do 'if mats'")
if mats:
    poser.DialogSimple.MessageBox("Done 'if mats'")

When I run the script the first message box (Gonna do 'if mats') appears, but then I get the Python print window with this

poser.error: Actor has no available material

I'm puzzled - the whole purpose of the 'if mats:' is to check for this. Still trying to make sense of this.

 


The 3Dcheapskate* occasionally posts sensible stuff. Usually by accident.
And it usually uses Poser 11, with units set to inches. Except when it's using Poser 6 or PP2014, or when its units are set to PNU.

*also available in ShareCG, DAZ, and HiveWire3D flavours (the DeviantArt and CGBytes flavour have been discontinued).



3dcheapskate ( ) posted Sat, 03 March 2012 at 6:30 AM

I've cut the script down to just a few lines to try and get to the bottom of this:

import poser
fig = poser.Scene().CurrentFigure()
act = poser.Scene().CurrentActor()
mat = poser.Scene().CurrentMaterial()
mats=[]
if act and not fig:
    yn = poser.DialogSimple.YesNo(" Current Actor: "+str(act.Name())+"nnChange all materials for this actor?")
    if yn == 0:
        act = None
    else:
        mats = act.Materials()
    
poser.DialogSimple.MessageBox("Check 'if mats is None'")
if mats is None:
    poser.DialogSimple.MessageBox("mats is None")
else:
    poser.DialogSimple.MessageBox("Done 'if mats'")

I start Poser 6 from scratch with just the default ground, cameras and lights. The Main Camera is selected by default.  I run the script either from an mt5 with just a 'runPythonScript' line or direct from File > Run Python Script, makes no difference. I get the "Check 'if mats is None'" and "mats is None" messages, and then this:

poser.error: Actor has no available materials

It's definitely the highlighted mats = act.Materials() that's causing it. If I change that line to mats = None then the poser.error doesn't occur.

Seems that I'll have to avoid calling the Materials() method if the actor doesn't have any materials. Anybody have any other thoughts on this?


The 3Dcheapskate* occasionally posts sensible stuff. Usually by accident.
And it usually uses Poser 11, with units set to inches. Except when it's using Poser 6 or PP2014, or when its units are set to PNU.

*also available in ShareCG, DAZ, and HiveWire3D flavours (the DeviantArt and CGBytes flavour have been discontinued).



adp001 ( ) posted Sat, 03 March 2012 at 11:11 AM

Wrap the material check with try/except. try: mat = actor.Materials() except poser.error: mat = None




3dcheapskate ( ) posted Sat, 03 March 2012 at 8:04 PM · edited Sat, 03 March 2012 at 8:07 PM

No joy, tried that already - same problem! Just to be sure I edited the cut-down script from the previous post...

import poser
fig = poser.Scene().CurrentFigure()
act = poser.Scene().CurrentActor()
mat = poser.Scene().CurrentMaterial()
mats=[]     # It was picking up previous mats?
if act and not fig:
    yn = poser.DialogSimple.YesNo(" Current Actor: "+str(act.Name())+"nnChange all materials for this actor?")
    if yn == 0:
        act = None
    else:
        try:
**            mats = act.Materials()**
**        except poser.error:**
**            poser.DialogSimple.MessageBox("error")**
**            mats = None**
    
poser.DialogSimple.MessageBox("Check if mats is None")
if mats is None:
    poser.DialogSimple.MessageBox("mats is None")
else:
    poser.DialogSimple.MessageBox("mats isn't None")

...sure enough, same problem. Note: the 'except' doesn't catch it either - I don't get the "error" message box. Curiouser and curiouser.

But like I said before, I can work round the problem with this:

if not act.IsCamera():
        mats = act.Materials()
else:
        mats = None

That works. What puzzles me most is that the error doesn't show up until the end of the script. It would be nice (but not essential) to know what the heck is going on here!

(by the way, I'm using Poser 6. Is this just a Poser 6 issue? Can Somebody check the problem in Poser 7/8/9? Just run the cut-down script from my previous posts with no figure in the scene and the Main Camera selected.)


The 3Dcheapskate* occasionally posts sensible stuff. Usually by accident.
And it usually uses Poser 11, with units set to inches. Except when it's using Poser 6 or PP2014, or when its units are set to PNU.

*also available in ShareCG, DAZ, and HiveWire3D flavours (the DeviantArt and CGBytes flavour have been discontinued).



adp001 ( ) posted Mon, 05 March 2012 at 4:28 AM · edited Mon, 05 March 2012 at 4:29 AM

If I open a Python-Shell in Poser (2012) and execute: sc=poser.Scene() type(sc.Cameras()[0].Materials()) The answer is: type 'NoneType' No error-message. So the result is just None.




3dcheapskate ( ) posted Tue, 06 March 2012 at 9:07 AM

file_479196.jpg

Like I said, it's an odd one. The **mats = act.Materials()** line definitely sets mats to None, exactly as we'd expect (the if mats is None: / poser.DialogSimple.MessageBox("mats is None") proves that), but somehow also flags an error that isn't caught by using a try: / except: ...

Anyway, just uploaded the script to the Renderosity Freestuff - should be appearing there soon. Here's the first of two images to help people who want to try it out.


The 3Dcheapskate* occasionally posts sensible stuff. Usually by accident.
And it usually uses Poser 11, with units set to inches. Except when it's using Poser 6 or PP2014, or when its units are set to PNU.

*also available in ShareCG, DAZ, and HiveWire3D flavours (the DeviantArt and CGBytes flavour have been discontinued).



3dcheapskate ( ) posted Tue, 06 March 2012 at 9:08 AM

file_479197.jpg

And here's the second image. Lots of dialogues.


The 3Dcheapskate* occasionally posts sensible stuff. Usually by accident.
And it usually uses Poser 11, with units set to inches. Except when it's using Poser 6 or PP2014, or when its units are set to PNU.

*also available in ShareCG, DAZ, and HiveWire3D flavours (the DeviantArt and CGBytes flavour have been discontinued).



nruddock ( ) posted Tue, 06 March 2012 at 1:25 PM

The message you posted isn't an error (it's clearly not a stack trace) but a warning/informational one (it could even be debugging output left in the release) so it's not surprising that the try ... except isn't catching anything because no exception is being thrown.


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.