Forum Moderators: Staff
Poser Python Scripting F.A.Q (Last Updated: 2024 Dec 02 3:16 pm)
I suggest that you do not use:-
material.SetDiffuseColor(r,g,b)
because it has become outdated.
Work on the shader tree as shown below:-
<br></br>
# script to change diffuse colour<br></br>
# For simple materials with no textures or extra shaders the<br></br>
# lines below will work.<br></br>
#<br></br>
# import poser<br></br>
# material = poser.Scene().CurrentFigure().Materials()[0]<br></br>
# material.SetDiffuseColor(0.123, 0.345, 0.456)<br></br>
#<br></br>
# However with anything more complex use the script below<br></br>
# because this will control the shader tree whereas the above<br></br>
# only affects what may be considered as "legacy"
materials.
import poser
material = poser.Scene().CurrentMaterial()
shaderTree = material.ShaderTree()
poserSurface = shaderTree.Node(0)
diffuseNode = poserSurface.InputByInternalName("Diffuse_Color")
diffuseNode.SetColor(0.6,0.2,0.2)
shaderTree.UpdatePreview()
scene.DrawAll()
Lol yep, I did too. Now everything works.
I tried to add to the script to make it recurse through all figures and materials. Came up with this.
import poser
#declare variables
scene = poser.Scene()
allfigs = scene.Figures()
#set FOR loop to recurse through figures
for figure in allfigs:
#declare materials
mats = figure.Materials()
#FOR loop to recurse through materials
for material in mats:
#declare shader tree down to diffuse node
shaderTree = material.ShaderTree()
poserSurface = shaderTree.Node(0)
diffuseNode = poserSurface.InputByInternalName("Diffuse_Color")
#apply color
try:
mat.diffuseNode.SetColor(1.0,0.2,0.2)
except:
pass
#refresh scene
shaderTree.UpdatePreview()
scene.DrawAll()
print "Done"
at line 11, "for material in mats", I get the error
for material in mats:
^
SyntaxError: invalid syntax
What I am trying to do with that line is go through all materials for a figure and apply the color to each.
That's something that confused me. How do I assign/declare mat to be the material? Does Python know that
for mat in mats
means that "mat" means "whatever is lower in the tree from mats(defined)?"
I think I need a good flowchart of the hierarchy in order to get the recursive stuff sorted out. Or I may just be over thinking it, if my above assumption is correct.
Sorry about the indentation, when I did copy/paste it didn't keep the formatting. I'll be careful of that. The formatting was correct in my text editor, though.
The forums here tend to mess up formatting, so no worries there.
In python for x in y: y must exist and be a iterable variable. X is the variable that exch value gets placed in, and can be anything. You might find the python manuals to be a help, the Poser document only covers specific poser functions.
http://www.python.org/ has the manuals but make sure you get the right version.
Thanks for the link, I need to go read those manuals again. I even tried using your set minshader script as a reference since it can recurse through everything, but no matter what I do I get either syntax errors or iteration errors. I'll go through the manuals and see if that doesn't set me straight, then report back.
I am happy to report that after way too long I have been able to make some progress, and learn some things as well. This script has evolved a bit, my goal is now to be able to take any material set and strip it down to the bare essentials. My motivation for doing this is that
Older material sets employ "tricks" that are no longer necessary and don't work well with render gamma correction, IDL, and now built-in SSS
Complex shader trees are not needed with and sometimes don't even work with Pose2Lux and other exporters
3) I've been lurking long enough and have learned quite a lot since I first found this website, so now I want to start contributing
So... this script is intended to clean out the surface node, for example get rid of the kd_lite_multiplier, diffuse colors, ambience, etc. that were used way back in the day but are no longer needed. Then, follow the connections from the color inputs down to the image maps and plug those image maps directly to the color inputs. Then the user can apply the new SSS, or VSS, or whatever without worrying about things going haywire, or export to another program/renderer without having an all black figure because the maths didn't bake properly.
Here is what I have so far:
import poser
#declare materials
mats = poser.Scene().CurrentFigure().Materials()
shaderTree = poser.Scene().CurrentMaterial().ShaderTree()
for mat in mats:
shaderTree = mat.ShaderTree()
node = shaderTree.NodeByInternalName("PoserSurface")
node.Input(0).SetColor(1.0,1.0,1.0)
node.Input(1).SetFloat(0.8)
node.Input(2).SetColor(1.0,1.0,1.0)
node.Input(3).SetFloat(0.2)
node.Input(6).SetFloat(0.0)
node.Input(20).SetFloat(0.0)
#node.Input(21).setInput(0)
#Function to test if a node is an image map
def testIMG():
Diff_Color_Input = node0.InNode()
node2 = Diff_Color_Input
node2_type = node2.Type()
print node2_type
if node2_type == "image_map":
print "node is an image map"
return
else:
print "Node is not an image map, moving to next input..."
node1 = node2
node2 = node1.InNode(0)
testIMG()
#Find Diffuse image map
for mat in mats:
shaderTree = mat.ShaderTree()
node = shaderTree.NodeByInternalName("PoserSurface")
Diff_Color = node.InputByInternalName("Diffuse_Color")
node0 = Diff_Color
testIMG()
shaderTree.UpdatePreview()
poser.Scene().DrawAll()
Forgive me if I missed an indent or such, that is a copy/paste from my editor and then liberal use of the spacebar applied.
I have hit a couple problems so far. The biggest is that the script exits with
Traceback (most recent call last):
File "V:Pythonmats.py", line 40, in ?
testIMG()
File "V:Pythonmats.py", line 23, in testIMG
node2_type = node2.Type()
AttributeError: 'NoneType' object has no attribute 'Type'
as the error. I thought the "return" command would break the function, but it appears it isn't doing what I thought it would. As a sidenote to that, I'm pretty sure there is a problem with how I am reassigning the nodes after the "else:" line.
The other is the line
#node.Input(21).setInput(0)
I cannot for the life of me get the Reflection_kd_Mult to uncheck in the script. It worked fine for Reflection_lite_mult by giving it a 0.0 floating number. For what it's worth I ran a Type() command on the Reflection_kd_Mult and Poser returned "4", whatever that means. Oh, and I know it has a # in front, I just stuck that there so I could move on to other things for the time being.
I would suggest you not use Input(x) although it does work. If poser adds something to PoserSurface it will break, and it makes it hard to undrstand what is going on.
the firt shadertree statement seems like its not needed.
Node(0).InNode() i think is wrong - InNode(0 is a input method)
so Diff_color_input = Node.Input(0).InNode() is what you need
dont understand this at all:
print "Node is not an image map, moving to next input..."
node1 = node2
node2 = node1.InNode(0)
testIMG()
its saying make node1 = node2
then its wrongly trying to get the node connected to node1
that wont work.
#node.Input(21).setInput(0) try setfloat(0)
try fixing you Innode problem and see what breaks then ;-)
oh, by the way look at the shader type codes near the beginning of the poser manual.
they are defined words like kTypeCodeAMBIANTOCCLUSION which can be used to compare a node type.
use them like this AOnodetype = poser.kTypeCodeAMBIANTOCCLUSION
if node2_type = AOnodetype:
or directly if node2.type = poser.kTypeCodeAMBIANTOCCLUSION :
Quote - I would suggest you not use Input(x) although it does work. If poser adds something to PoserSurface it will break, and it makes it hard to undrstand what is going on.
Good point, I'll change it to use internal names when I do the cleanup.
For the poser surface I tried
node.Input(21).setFloat(0)
before but it didn't work. I SHOULD have used
node.Input(21).SetFloat(0)
^
been getting bitten by capitalization all day, glad I noticed that.
Quote - dont understand this at all:
Print "Node is not an image map, moving to next input..."
node1 = node2
node2 = node1.InNode(0)
testIMG()
its saying make node1 = node2
then its wrongly trying to get the node connected to node1
that wont work.
I agree, I took it out for now to do more testing. What I was trying to do with that statement is:
A B C
PoserSurface(Diffuse Color)input ->non image map node -> image map node
Node A is the current focus, so find the input for that node, which is node B. Yes? Cool, exit the function and move on. No? Ok, focus on node B, and grab its input which is node C. Restart the loop and test again. The problem with doing it cut and dry like that is that I don't know how many extraneous nodes are in the path before I hit the image map, and I need a way to feed node B to the beginning of the function so it doesn't keep trying to start with node A over and over again. Probably have to use an incremented integer with a FOR loop. Or something.
For testing the node, I followed your input and rewrote it to
if node2.Type() == poser.kNodeTypeCodeIMAGEMAP:
but it still didn't work. Here is what is really confusing me on that whole part part. The line
print node2.Type()
returns image_map. So if I use
if node2.Type() == "image_map":
Python returns
image_map
node is an image map
fourteen times, the the attribute error
File "V:Pythonmats.py", line 40, in ?
testIMG()
File "V:Pythonmats.py", line 24, in testIMG
print node2.Type()
AttributeError: 'NoneType' object has no attribute 'Type'
But if I use
if node2.Type() == poser.kNodeTypeCodeIMAGEMAP:
I still get
image_map
node is an image map
returned fourteen times, then I get the same attribute error. It seems like Python is reassigning node2, even after I took out all that funky node1 = node2 stuff. Almost forgot, I checked the typecode with the Poser Python Methods manual as well as Phillc's book, and they both used the same code, so no luck there.
your testimg routine is called from a for mat in mats: do you have 14 materials in that figure ?
I would say when your else clause executes then your fault occurs. If you have corrected the logic to get the node input innode you also need to account for each input in the node.
for example a blender node may be connected to the diffuse color input, blender node has three inputs, so an image map may be logged into one , two or all three inputs.
example skin image map to input 1, tatoo image map to input 2 and a mask image to input 3.
I have no idea how you sort that out :-(
remember though you can build a list of nodes and then go back and work through the list.
could you post you script again ? attach a copy as a txt file would be fine.
I have only used the first material for testing. You should be able to fix it to loop through all materials.
If the len(imgnodes)==1 then there will only be one image node and you can use the name to get the node and connect it directly to the diffuse channel.
the script should be recursive through the chain of nodes. I have only tested it with three nodes in the chain.
hope this helps
That makes sense. I didn't think to account for a mat with no nodes into the diffuse channel. I'm eager to see the script you posted, because I realized that if I hit a node with multiple inputs that will open up a world of hurt. It will be late before I get home, but I will post the full version of what I have so far when I do.
I took a closer look at the script you posted, and I like your idea of using a list. My way, were I able to get it working, would get very ugly very fast. With that being said, don't pay much attention to the attached file, since I will pursue a new course of action with a list.
As to your example with the blender node, you raise a very good point. I don't think it would break the process, but would reduce the number of successful outcomes to 1/number of image maps in the chain. I can't think of any way to avoid that without being able to find some clue or assignment left by the developer, but since there isn't really standardization I don't see that being possible. I'm not too worried about it though, since I can't think of a single product that uses proper application of the node system (but not saying there aren't any out there); most products I see/own simply change the reference image to deal with masks, tattoos, etc.
I'm done for tonight, gonna play with it tommorrow and report back.
Attached Link: Scene Fixer script
Hi 232,You might find this script useful as reference - it trawls through the scene elements in a similar fashion to that which you are doing.
Free stuff @ https://poser.cobrablade.net/
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.
import poser
scene = poser.Scene()
materials = poser.Scene().CurrentFigure().Materials()[0]
diffcol = materials
print diffcol
materials.SetDiffuseColor(1.0, 0.1, 0.1)
diffcol2 = materials
print diffcol2
scene.DrawAll()
print "Done"