• Welcome to the Community Forums at HiveWire 3D! Please note that the user name you choose for our forum will be displayed to the public. Our store was closed as January 4, 2021. You can find HiveWire 3D and Lisa's Botanicals products, as well as many of our Contributing Artists, at Renderosity. This thread lists where many are now selling their products. Renderosity is generously putting products which were purchased at HiveWire 3D and are now sold at their store into customer accounts by gifting them. This is not an overnight process so please be patient, if you have already emailed them about this. If you have NOT emailed them, please see the 2nd post in this thread for instructions on what you need to do

Help! I need some poser python scripts and am getting lost

Dreamer

Dream Weaver Designs
I am trying to write some small scripts to change the settings of some nodes with in a shader setup and I am getting totally lost and confused. I have taken basic coding in the past but struggled to really get my head round some of the more complicated things.
Any help would be most welcome
 

kobaltkween

Brilliant
Contributing Artist
What kind of help are you looking for? I can say that in general what you have to do is traverse the node tree, test for whether you're on the node you want or not, then change its properties. But I might have a better idea if you show me what you have so far and are more specific about what you're trying to do.
 

Dreamer

Dream Weaver Designs
There are three maybe four different things I want to try and do but for the moment I am just working on one to change the setting of the Reflection_Value to 1.0, .5 and .25 with out touching any thing else in the shader set up. (I'm woking on some textures for the Hivewire Unicorn and want a way for the end use to be able to pick the glossiness of the horn). There being one for each of the levels, not one to do all three.

So far I have a bit of code that looks like this:

import sys
import poser
pathname = os.path.split(poser.AppLoaction())[0]
pathname = os.path.join(pathname, 'Runtime', 'Python', 'poserScripts', 'DreamWeaver Designs', 'HiveWire Horse')
sys.path.append(pathname)


if float(poser.Version()) >= 9.0:
import HoofGlossLow
HoofGlossLow.DoIt()


It all most worked but gave an error saying HoofGlossLow was not a valid some thing, sorry I can't remember what it was input maybe?
I had originally set it up with Advanced Shaders 1.5 but that requires the end user to have it as well and while the plugin is free I'd rather not rely on a 3rd party plugin in case it ether vanishes or the end user doesn't want to install it for what ever reason.

I hope that has cleared things up a bit :)
 

Gadget Girl

Extraordinary
Contributing Artist
So here's my first thought. I like to start out with a simple script I run manually, then figure out how to 'hook' it up to other things in Poser.

In your HoofGlossLow script I would make the last line:

Code:
DoIt()

So that it will auto run if Poser loads the file. Then under the File menu in Poser, choose "Run Python Script" this will let you browse to wherever the script is located on your computer and run the script without calling it from elsewhere.

That way you can troubleshoot your HoofGloss script without worrying about if the problem is how you are calling the script, or a bad file path, or whatever.

Also so you know, you can run python scripts from .pp2 files which may be way easier than what you are trying to do. For instance in my most recent set of dynamics clothing items I created some fake 'props' that sat in the same folder as the dynamic clothing items. When you click on the prop called NewClothSim it calls a .pp2 file that just looks like this:

Code:
{
version
    {
    number 5
    }
runPythonScript ":Runtime:Python:poserScripts:GadgetGirl:AoDaiDawn:NewClothSim.py"
}

That's the entire file.

Hope that helps.
 

kobaltkween

Brilliant
Contributing Artist
So, here's a basic form of script for setting the value of an input on a the root node , with {{placeholder}} as the form for the places you should put your own values.

import poser

# get the currently selected actor
actor = poser.Scene().CurrentActor()
# get the material you want
yourMat = actor.Material({{YourMatZone}})

# get the image nodes from that material
if (yourMat):
root = yourMat.ShaderTree().Node(0)
nodeInput = root.InputByInternalName({{YourInputSlot}})
nodeInput.SetFloat({{YourValue}})


Essentially, Poser Python scripting is about using the documentation to figure out what objects you need to use to get to what you want, then figuring out which methods you need to manipulate what you want. The big things to remember are:
  • The Poser API is almost all about methods not properties, so you use methods to get properties and set their values rather than doing that directly
  • Python is case sensitive, and almost all methods begin with capitals
  • Most of the main structures in Poser are trees. Figures, shader trees, etc. So understanding tree traversing algorithms will probably help with your Poser scripting. That said, I've worked with Matmatic and plain Poser Python, and I'm still weak on tree traversal.
 

Dreamer

Dream Weaver Designs
Thanks kobaltkween, just to clarify, the ({{YourInputSlot}}) would, in this case be Refection_Value and the (yourMat) would be the name of the node plugged into it like say Fresnel_Blend?
 

Dreamer

Dream Weaver Designs
Too late to edit the above post.
The (yourMat) is not a node it is the name material file you are changing correct?
 

Dreamer

Dream Weaver Designs
Ok so I just tried this and got a error

*file path snipped* line 6
yourMat=actor.Material(1_Hoof)
^
SyntaxError: invalid syntax
 

Gadget Girl

Extraordinary
Contributing Artist
I'm pretty sure the problem is that you aren't passing a string. It should be:

Code:
yourMat=actor.Material("1_Hoof")

unless you have previously declared a variable 1_Hoof = "1_Hoof".
 

Dreamer

Dream Weaver Designs
Ah thanks Gadget Girl, I had a feeling I had missed some silly little thing. I'll try that out as soon as I can, got a lot on this weekend away from computer :)
 

kobaltkween

Brilliant
Contributing Artist
Thanks kobaltkween, just to clarify, the ({{YourInputSlot}}) would, in this case be Refection_Value and the (yourMat) would be the name of the node plugged into it like say Fresnel_Blend?
Too late to edit the above post.
The (yourMat) is not a node it is the name material file you are changing correct?

Yes to the first part, and you seem to have figured out the second part. Just to be clear, you're dealing with the root node itself (Node(0) specifies the 0th node, which is the first node or the root one), not what's plugged into it. Which, for Poser's materials, is separate from the value of the input. So that script works whether or not something is plugged into the input you're changing.

Also, as is, you won't see changes to the interface. So if you run the script and you're in the material room looking at the material in question, you'll have to go to something else (another room, another material, etc.) and go back to get the screen to redraw. I think there's a way to force the redraw, but I'm not finding it yet.
 

Dreamer

Dream Weaver Designs
Yes to the first part, and you seem to have figured out the second part. Just to be clear, you're dealing with the root node itself (Node(0) specifies the 0th node, which is the first node or the root one), not what's plugged into it. Which, for Poser's materials, is separate from the value of the input. So that script works whether or not something is plugged into the input you're changing.

Also, as is, you won't see changes to the interface. So if you run the script and you're in the material room looking at the material in question, you'll have to go to something else (another room, another material, etc.) and go back to get the screen to redraw. I think there's a way to force the redraw, but I'm not finding it yet.
Thanks, so the (yourMat) I change to (IvoryMat) or what ever its called. What if I want the one script to work on any mat applied to the hoof not just a specific one?
 

Gadget Girl

Extraordinary
Contributing Artist
Thanks, so the (yourMat) I change to (IvoryMat) or what ever its called.

So if I'm reading @kobaltkween's code correctly, yourMat is actually the material zone you are trying to effect, so you are creating a reference to 1_Hoof, or 1_InnerMouth etc. Using the approach here, you're never really dealing with your material in terms of the mc6 files saved to your library. Think of it as using the script to make a new version of the material already applied to the figure. So Poser really doesn't care that your material is called IvoryMat, or RainbowPony, or Rubber, or whatever.

You could write a script that did search the library for a material of a specific name and apply it to specific body parts and in that case you would care about the name of the material in the library, but I don't think that's really what you want to do here.

What if I want the one script to work on any mat applied to the hoof not just a specific one?

I can think of two ways to go about this.

If you are only changing the hoof materials then you could create an array that holds all the materials and then run your code if the material name contained hoof. So something like this:

materials = actor.Materials()
for m in materials:
if "Hoof" in m.Name():
#code here to make the changes you want.​

But since you said you were working on the unicorn, I'm thinking you might want the same code to run on both Harry and his hooves as well as the Unicorn horn, which means you want to run the same code on differently named materials on different figures in that case I might do something like this:

def ChangeGlossyness(matZoneToChange):
#code here to make the changes you want.​

You would call the function by doing something like this:

yourMat=actor.Material("1_Hoof")
ChangeGlossyness(yourMat)

You could then call that function several times passing in the material you wanted to change. So you would call it twice for both hoof materials. Then find the horn figure and run it on it's materials.
 

kobaltkween

Brilliant
Contributing Artist
If you want to change Poser Material presets, the only API is the one Bagginsbill made, Matmatic.

The script as it is works on any mat applied to the hoof, since any mat has a root node and you're one or more of its inputs (in your case, Reflection_Value). If what you want to do is change any material _zone_, then do it more like Gadget Girl describes above.

Just as an example, I used a more involved script with the same base in my Essential Materials for my Nylon - 2nd Skin. It can take any material with textures plugged into the root node and create a new layered nylon/skin material using the original textures. It works with pretty much all the characters I've come across. That said, I had to make one specifically for V4 and her zones, and for Dawn and hers.
 

Dreamer

Dream Weaver Designs
Thanks both of you, I have had a pretty big weekend and am rather shattered. I'll come back and go over what you have written tomorrow when I hope to be a bit more with it:sleep:
 

Dreamer

Dream Weaver Designs
:happyflip::happyflip::happyflip: I did it!!! I have a working script! :bounce: Thank you both so much, now just to do the little bit that calls it when you use a dummy mc6. Sjould be easy right? lol
 

Dreamer

Dream Weaver Designs
Ok now I have that one working right I need to enlarge on it slightly. I need to be changing not just the Reflection_Value but also the roughness and Ks values of a ks_microfacet node pluged into the Alternate Secular.
The first part of the code would be the same but the second part would need more added, not sure what but lets see if a can puzzle a bit out.
If the root node is 0 I am guessing that the first node plugged into it in any channel is 1, so there would need to be some way to pinpoint the ks node as the one I want the script to change in the second part of it. Some thing like:

if (yourMat):
xxxx = yourMat.ShaderTree().Node(1)
nodeInput = xxxx.InputByInternalName("ks_microfacet")
nodeInput.SetFloat(.05)
nodeInput.SetFloat(.025)


How far off the mark am I? (the xxxx is just there as a holder for what ever it is that needs to put in instead of root to get it pointed at the right place) :)
 

Gadget Girl

Extraordinary
Contributing Artist
So this script is designed to be used with a specific set of materials you are making right? I say that, because the easiest thing to do might not be universal if some say had more than one ks_microfacet Node, or named it something else this would break, but otherwise it would work fine.

So lets say the Material you are working on is called mat. Then

Code:
ksNode = mat.ShaderTree().NodeByInternalName(ks_microfacet)

ksInput = ksNode.InputByInternalName("ks_microfacet")

ksInput.SetFloat(0.05)

So as long as you only have one node with that name, you can just search for it in the ShaderTree using the NodeByInternalName() method.

Does that help?
 
Top