Forum: Poser Python Scripting


Subject: Python can set a render-engine and render, but can it also call a preset?

HartyBart opened this issue on Dec 05, 2020 ยท 23 posts


HartyBart posted Sat, 05 December 2020 at 3:42 PM

It's a simple matter to have a Python script trigger a render from Poser 11, in a specified sender-engine, thus....

scene.SetCurrentRenderEngine(poser.kRenderEngineCodePREVIEW)
scene.Render()
scene.SaveImage("png", "C:\Users\My_name\render.png")

But let's assume that the user already has a saved and named render preset for that engine. Can this saved preset also called, by name and file-path? If so, how, please?



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


HartyBart posted Sat, 05 December 2020 at 3:46 PM

The forum software has auto-removed the double in the file path shown above. Assume (without a space between them) and not in the path used to save the rendered image.



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


HartyBart posted Sat, 05 December 2020 at 3:49 PM

Oh for heaven's sake, now it's removed all the slashes entirely??? Renderosity, please update this crappy old forum software!!!!



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


HartyBart posted Sat, 05 December 2020 at 3:51 PM

It's 2020, and I'm in a forum that forces me to resort to a screenshot to show working code properly...

2020-12-05_215035.jpg



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


adp001 posted Sat, 05 December 2020 at 7:41 PM

But let's assume that the user already has a saved and named render preset for that engine. Can this saved preset also called, by name and file-path? If so, how, please?

I didn*t test it, but: As you may know, the presets are stored like CR2/PP2 files. Typical Poser format. So maybe it's possible to load them with a "LoadLibrary..." function.




adp001 posted Sat, 05 December 2020 at 8:10 PM

Here is what I mean:

{

version
    {
    number 11
    }
    renderDefaults
        {
    superFlyOptions
        {
        aaSamples 3
        advancedSamplingControls 1
        aoSamples 1
        causticsReflective 0
        causticsRefractive 0
        depthOfField 0
        deviceType 0
        diffuseSamples 3
        filterGlossy 1.000000
        glossySamples 2
        maxBounce 3
        maxDiffuseBounce 1
        maxGlossyBounce 2
        maxTransmissionBounce 4
        maxVolumeBounce 0
        meshLightSamples 2
        minBounce 1
        motionBlur 0
        progressiveRefine 0
        sampleAllLightsDirect 1
        sampleAllLightsIndirect 1
        sampleClampDirect 10.000000
        sampleClampIndirect 10.000000
        spatialSplit 1
        subsurfaceSamples 3
        tangentSpace 1
        tileSize 32
        transmissionSamples 2
        transparentBackground 0
        transparentMaxBounce 16
        transparentMinBounce 4
        transparentShadows 1
        volumeMaxSteps 1024
        volumeSamples 1
        volumeStepSize 4.000000
        deviceID CPU
        }
        }
}



HartyBart posted Sun, 06 December 2020 at 4:12 AM

Thanks for the tip. I see that the PoserPython Methods manual has a half dozen LoadLibrary examples, such as LoadLibraryCamera and LoadLibraryLight, but no LoadLibraryPreset.

I guess what's meant to be used instead is the LoadPreset command, as noted elsewhere in the PoserPython Methods manual. This has no working example in the manual, but can apparently load a saved PRP preset file (FireFly and presumably also SuperFly).

I've tried the following basic loader script and am getting nowhere. The "scene." in scene.LoadPreset stops the script and seems to need to be something else, but I have no clue what it needs to be. Adding double-slashes in the file path make no difference.

presetscript.jpg



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


HartyBart posted Sun, 06 December 2020 at 4:36 AM

Success. It's now working, with this. The magic doohickey was "action." for LoadPreset, and the solution was found in PhilC's paid scripts pack/book.

working.jpg



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


HartyBart posted Sun, 06 December 2020 at 5:03 AM

And here's a working example of how you have a script render a Sketch PZS preset (even though you're not supposed to be able to)....

sketch.jpg



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


adp001 posted Sun, 06 December 2020 at 7:06 AM

Nice.

But I really did mean "LoadLibraryPose". With this I can load parameters for dynamics and other stuff. Or weightmaps. Anything that is part of a PZ2/PZ3 file (anything means: anything I tried). Prepare a correctly written block and Poser will take it.

These "pzs" files are formatted like renderparts from a PZ3.

I can't test it myself. No Poser around at the moment. Only Blender :)




maur_2005 posted Tue, 08 December 2020 at 4:28 PM

Nice.

It would be great to save the image with the same name of the current Poser file...

The question is, how can I get the name of the current Poser file?


HartyBart posted Tue, 08 December 2020 at 8:43 PM

"It would be great to save the image with the same name of the current Poser file"

Good idea.

One way to do such a task would be to have the script output your preview.PNG, firefly.PNG, sketch.PNG, etc, to one standard location such as a "my_new_renders" folder. No complex re-naming or manual editing is then required within the script. Then at the same time you could have the script save the Poser scene file by using poser.SaveDocument command, where the Methods Manual states "If you do not specify an argument, the file will be saved in its current path with its current name."

After running the script you would thus end up with a folder with....

scene001.PZ3

sketch.PNG

firefly.PNG

preview.PNG

Then you'd have a macro watching that folder and auto-renaming PNG files as they arrived, according to a file mask taken from the last-saved PZ3 filename in the folder. Thus any sketch.PNG would automatically become scene001_sketch_001.PNG and so on. Then you would be safe to run the script again, knowing that the next saves would become scene001_sketch_002.PNG and so on.

The problem there is if you are then planning to combine your renders with a Photoshop Action that loads and juggles named files, and as such cannot cope with any filename iteration. The Action expects, every time, to load...

sketch.PNG

firefly.PNG

preview.PNG

... and then to name layers accordingly.

In which case it's not the files but their folder that must be re-named, to something like my_new_renders_scenename_renders001. To do this a macro would be watching the save folder, do the rename according to the name of the PZ3 found in the folder, and would then create a fresh my_new_renders folder - ready to receive the script's next batch of renders. On future runs the macro would know to increment the new folder name, from my_new_renders_scenename_renders001 to my_new_renders_scenename_renders002 and so on.

This would require a lot of hard-drive space, since each time you're saving a new .PZ3 so as to get the scene filename, but if you're doing that kind of production then you have that kind of space.

Perhaps all this could be done in Python via using methods such as os.rename and os.path.exists and fileName.split and suchlike - but I'm not sure if PoserPython can do that or if Poser would be allowed to do such things at the file/folder level by the OS. Another way might to have the end of a Python script call a BAT file, but I've no idea how to do that either. Can PoserPython call and run BATs?



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


adp001 posted Tue, 08 December 2020 at 9:14 PM

maur_2005 posted at 9:11PM Tue, 08 December 2020 - #4406742

Nice.

It would be great to save the image with the same name of the current Poser file...

The question is, how can I get the name of the current Poser file?

filename, _, _ = wx.GetTopLevelWindows()[0].GetLabel().partition("-")

(those underscores are intentional and are used as placeholders if variables are not used)

If no scene is loaded filename becomes "Untitled".




adp001 posted Tue, 08 December 2020 at 9:21 PM

HartyBart posted at 9:18PM Tue, 08 December 2020 - #4406760

Perhaps all this could be done in Python via using methods such as os.rename and os.path.exists and fileName.split and suchlike - but I'm not sure if PoserPython can do that or if Poser would be allowed to do such things at the file/folder level by the OS.

You can do anything with Poser Python on the file system what the user Poser runs under is able to do. Even formatting the whole disk :)




HartyBart posted Tue, 08 December 2020 at 9:24 PM

re: BAT files, Poser Outlaw's old script - Poser OBJ Export to Cycles (meaning, Blender) script may be helpful, one that that worked with the mcjteleblender2 exporter before Poser 11 had Cycles natively.

It has sophisticated examples of PoserPython working with folder naming, renaming and also making(!) and calling a BAT file.

from subprocess import Popen

Popen(runBat, cwd=dst)

It also seems to be getting something called basefilename to get the scene filename, a method unknown to the PoserPython Methods Manual.



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


adp001 posted Tue, 08 December 2020 at 9:39 PM

HartyBart posted at 9:36PM Tue, 08 December 2020 - #4406765

It also seems to be getting something called basefilename to get the scene filename, a method unknown to the PoserPython Methods Manual.

Nope. Nothing like "basefilename" in Poser Python. You can check that with my FAKEPOSER lib. Anything Poser Python knows is in it, extracted directly from a running Poser; anything included what is not mentioned in the manual.




HartyBart posted Tue, 08 December 2020 at 10:36 PM

Thanks ADP.

After looking at some examples, I see that Popen is not needed to run a BAT. I bodged the following simple working Python script, to call and run a BAT file via Poser 11 Pro. Useful for reference re: future readers of this thread, though I recognise that it would be better and more cross-platform to do complex folder/file renaming in the Python code itself.

working.jpg

Note the double backslashes need on the file path.



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


adp001 posted Tue, 08 December 2020 at 11:17 PM

I think fileoperations in Python are simple enough.

For strings used in file operations it may be useful to use strings like this:

filename = r"C:\another\folder\myfolder\file.bat" (note the "r" in front of the string).

But more better and more compatible (Poser is also available for Mac): Avoid the drive letter. and use "/" instead of "". Only windows uses this strange spelling with file- and pathnames.




adp001 posted Tue, 08 December 2020 at 11:21 PM

(I give up with this damned editor - I'm simply not able to add \ where I need it. And the edit function removes it again and again)




adp001 posted Tue, 08 December 2020 at 11:23 PM

Here is anything one needs to know about filehandling in Poser:

https://docs.python.org/3/library/os.path.html

or for P11 and below:

https://docs.python.org/2.7/library/os.path.html




HartyBart posted Wed, 09 December 2020 at 12:58 AM

Many thanks. I got it working. If used in a larger script, the following tested and working Poser 11 script renames the folder of saved renders to a new 'scene-name + timestamp' folder, then it re-creates the old folder ready to receive more renders on the script's next run. Doing it this way keeps the render filenames intact, and thus allows an automated Photoshop Action to run on them. I changed your code suggestion slightly, to accommodate those who 'have-filenames-like-this' for their Poser scenes.

working-timestamp.jpg



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


HartyBart posted Wed, 09 December 2020 at 2:17 AM

Thanks ADP, I hadn't known about the rawstring marker. That will make it easier for other users to edit the filepath in a script, instead of encountering the puzzling double-slashes.

As for the Mac problem, the difficulty there is that majority of those needing to manually tweak the file paths - re: output of renders, or input of presets - will be confused if they are faced with something that looks unlike what they can copy-paste from Windows Explorer, and which also appears to be worryingly missing its C: drive label.



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


adp001 posted Wed, 09 December 2020 at 3:57 AM

Nice how you solved the windowname grabbing with " - " :)

About drive letters: I have 4 of them with windows at the moment. Which one should I use now?

A sugestion: Use some sort of config file. It's pretty simple with a dictionary and Json.

Some snippets:

import os
import json
import time

Config = dict()
Config["mainpath"] = r"---------"
Config["finals"] = r"."
...
project_name, _, _ = wx.GetTopLevelWindows()[0].GetLabel().partition(" - ")
config_fname = "config_%s.cfg" % project_name

# write config.
with open(config_fname, "w") as fh:
    json.dump(Config, fh)

# read config
if os.isfile(config_fname):
    with open(config_fname, "r") as fh:
        Config = json.load(fh)

# save a render
render_engine = poser.Scene().CurrentRenderEngine()
render_engine_name = "SuperFly" if render_engine == poser.kRenderEngineCodeSUPERFLY 
    else "FireFly" if render_engine == poser.kRenderEngineCodeFIREFLY 
    else "Preview"

filepath = os.path.join(Config.get("mainpath", r"c:/"), project_name)
if not os.path.isdir(filepath):
    os.mkdir(filepath)
datetime = time.strftime("%d-%m-%Y/%H:%M", time.localtime())
filename = os.path.join(filepath, render_engine_name + datetime)

...