• 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

Learning Poser Python...

Ken1171

Esteemed
Contributing Artist
I have been learning to program with Poser Python. I have purchased Phillip Cook's tutorial, but it was not as good as I thought. We can learn Python from any book, so there wasn't necessary for him to try to teach the basics of the language there. What I want to know is how to use Poser Python, not Python itself. There are plenty of better and more complete books for plain Python in the market.

One thing that makes it harder is that Poser uses an older version of Python that has been retired by the mainstream academia nowadays. Most books are for current Python 3, while Poser uses old-school version 2.6. It's difficult to know if something doesn't work because of version differences, or because of the particular way Poser handles it.

Nonetheless, last night I have managed to make a script that builds a texture overlay, and inserts itself into the existing material on Dawn's face. This only works if the face texture is plugged into the "diffuse color" channel. For materials that use the "alternative diffuse", I would have to write some more code. I am not using any graphical interfaces yet, and I was happy enough when the script worked.

My grudge was when I wanted to reuse this code by turning it into a class. After that was done, I couldn't import the class in any possible way I have tried. I have tried this for 2 days and gave up. Now I suspect that for Poser Python to import a class, maybe it has to be placed in a special folder, or else it won't recognize it. I have also suspected that maybe Poser Python forces all code to be self-contained in the same file, so we cannot break the code into separate classes like we do in normal programming. I don't really know. In Poser, the "import" statement from regular Python only seems to work with pre-existing classes, but not with new ones we create.

To test that, I have examined scripts created by other people, but nobody seems to want to split a program into classes. All examples I have found contain all classes in the same file, which is not how good programming is done. This approach leads to confusing programs that are very hard to debug. Most examples don't even use classes, but instead just a list of function calls, which is even worse.

I am placing my Python files at "Runtime\Python\poserScripts\ScriptsMenu\Ken1171\". I have assumed that if all files are in the same folder, I could just import them straight away, but no - Poser Python doesn't let me import any files other than its own existing classes. Even when I have managed to import a class, it claims it doesn't contain any methods. This happens to both files with a class, or with just plain series of functions. It appears that Poser Python cannot import anything other than its own files?

Any hints on why this happens?
 

Miss B

Drawing Life 1 Pixel at a Time
CV-BEE
I signed up for a couple of Python classes at Udemy, one the basic language, and one for Programming Python for Blender. I haven't gotten to either class yet, so not sure where to even begin thinking about this issue. That said, I don't know if programming Python for use in Blender would be enlightening as far as programming Python for use in Poser.
 

Ken1171

Esteemed
Contributing Artist
The thing is - I already know Python, but only version 3. Poser Python uses old version 2.6, which has a different syntax in some areas. From all programming languages I have learned so far, Python seems to be the one that has the most of syntax changes of all. This is why every time Poser upgrades the Python version, all previously created scripts have to be rewritten. In other words, I know Python 3, but my code doesn't work in Poser. I am having to adapt to the old ways of Python 2.6, which feels like a step back.

You don't have to use classes to encounter the import issues in Poser Python. So far I couldn't import even a file with just a single function "def doNothing(): pass" that is in the same folder as the file calling it. Poser claims that either the file doesn't exist, or that it has no declarations/functions inside. What makes this really suspicious is that all code from other people I have seen so far ALWAYS put all code and classes in the SAME file. Nobody apparently wants to ever split the code into other files.
 

phdubrov

Noteworthy
Contributing Artist
A. Parmatic is an example of module structure with working import.
Did you make a proper module with __init__.py ?
B. Netherworks does not use imports of his own files, he uses poser.ExecFile(). But: he uses compiled files at the core, and the wx routine can be the reason to do so.
 

Ken1171

Esteemed
Contributing Artist
Parmatic is an example of module structure with working import.

Yes, I have classes that work in Python, but not in Poser Python. I have dug deeper in to PhilC's tutorial, and managed to import a file, but ONLY if it contains plain function declarations (not classes). I am used to Python 3 syntax, so I think the problem is that version 2.6 probably do this differently, so it might be syntax issue. When I import a class file, it tells me it contains no methods. I think Poser Python instantiates classes with a different syntax.

I think I am getting closer to the core of the problem.
 

Ken1171

Esteemed
Contributing Artist
Ok, I managed to import a class from another file, and instantiate it. I can print the object, and it claims to be instance of the class. But when I call a method of the class, it claims it doesn't exist. This is where I get stuck.
 

Ken1171

Esteemed
Contributing Artist
Haha.... Now I managed to make it work. Looks like if I make a change to the code, I have to restart Poser! I need to test the code as I write it. But do I need to restart Poser every time? It can't be THIS difficult...?
 

phdubrov

Noteworthy
Contributing Artist
Yes, just stumble on this WTF too.
But seems like it the case only when import is used.
 

phdubrov

Noteworthy
Contributing Artist
More precise: you can change the file you run. But the imported module is cached. Make sense, as all the scripts are running in one big __main__ session started with Poser.
So yeah, (easy) import only for rock-solid and tested libraries in Poser.
 

Ken1171

Esteemed
Contributing Artist
Yes, that kind of makes sense. One way around that is to test a class file individually before importing it in other files.

Ok, so now I can import and instantiate a class from another file, but I still can't call any methods from it. In Python 3, we use the standard ECMA dot notation, like:

0= ovl.Overlay() #Creates an instance of the class
o.createNewOverlay() #Calls method "createNewOverlay" from class "Overlay"

This works in Python, but not in Poser Python. When I call the method, Poser tells me it doesn't exist in the class. Why is that?
 

phdubrov

Noteworthy
Contributing Artist
Another way is to play with reload() on dev stage. (Reload is different in Python2!)

Do you import ovl or from ovl import Overlay ?

This works for me
Code:
from donothing import MyClass
my = MyClass()
my.f()
 

Ken1171

Esteemed
Contributing Artist
I have tried importing the class either ways:

import ovl
....and also
from ovl import Overlay

...and I get an error when calling any methods from the class. For example:

from ovl import Overlay
o= Overlay()
#OK until here....
o.createOverlay() <<== TypeError: createOverlay() takes no arguments (1 given)

It claims the method requires no parameters, but got 1. This has to do with the method call having parenthesis at the end. If I remove them, now I get no errors, but also the method is not called anyway. If I remove the parenthesis from the method declaration (since it has no parameters), I instead get a syntax error. So I am not sure when to use parenthesis after a method call in Python. Either ways the method call doesn't work.

o.createOverlay <<== Without paranthesis, no errors, and the method is not executed.

What I am doing wrong?
 

phdubrov

Noteworthy
Contributing Artist
Can't say without code.
dev example that works for me
Code:
#dosomething.py
import donothing

# dev mode
reload(donothing)
# dev mode

my = donothing.MyClass()
my.f()

# dev mode
my = None
del my
# dev mode
 

Ken1171

Esteemed
Contributing Artist
Aha! I have figured it out. Python makes a syntax distinction between the declaration of a function and a class method. A function call can be declared with no params, but a class method MUST have at least 1 param, which is a pointer reference to the class itself (self). For example:

def foo(): pass <--- regular function declaration
def foo(self): pass <--- a class method declaration inside the class

I was declaring class methods with no params, and that is not allowed. That's why I could never call them. We MUST pass a "self" as the first param in any method declarations on a class, or else things will not work. That was it! ^____^

PS: What's dev mode? Is it particular to Poser Python, or generic to Python itself?
 

Ken1171

Esteemed
Contributing Artist
Haha definitely an AHA moment! Now I have what I need to apply proper OOP methodology when writhing Poser Python code. This single class can create a texture overlay, and then inject it into the existing material on Dawn's face. With a small adaptation, I can reuse this class to do the same to any other MAT zone on the figure, therefore reusing it to inject an overlay to the entire body. All using this same class with different params. ^___^
 

Miss B

Drawing Life 1 Pixel at a Time
CV-BEE
So if I'm following your logic, you could use this to add a tattoo to any part of a character's body?
 

Ken1171

Esteemed
Contributing Artist
Remember the tabby cat stripes overlay I have created for Dawn? I am automating the application to any textures already applied. So far only works with "diffuse color" textures. I will have to expand to also include "alternative diffuse" channels. The overlays can cover anything - tattoos as well. I want to make the script data-driven, so a configuration text file can tell what to place where. :)
 

Ken1171

Esteemed
Contributing Artist
The class can already create all the shader nodes, name them, plug them to the right places, load the overlay texture, locate the right places and insert itself into the existing head material, assuming it uses the diffuse color channel. Next, I need to make another class to detect if the existing material uses the diffuse or alternative diffuse channel. Based on this, I can add some more code to cover all cases.

Next, I want to make it generic to be applied to any MAT zone. Then I will have something useful, but still with no GUI.
 
Top