• 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

PoserPython Wacros and Scripts - WacroMaterials()

3dcheapskate

Engaged
I write a PoserPython script that starts like this:

mats = poser.Scene().WacroMaterials()
if mats:
for mat in mats:
doStuff(mat)​

The script is on my desktop.

I assign my script to one of the ten wacro buttons(alt-click a wacro button to remove the existing assigned wacro, then click the button (now labelled '...') to select and assign my script)

If I now run my script by clicking the wacro button it runs for the current material only, as expected.
If I run my script by shift-clicking the wacro button it runs for the all materials of the current object, as expected.

If I run my script via File > Run Python Script it sometimes runs for just the current material, but sometimes for all materials of the current object. It seems to depend on how I last ran a wacro from one of the ten buttons.

It appears as if running a wacro from one of the ten buttons sets/clears a global flag that indicates current/all materials, and it seems that WacroMaterials() builds a list of mats for the current object based on the current setting of this flag.

Does anybody have any insight into this ?
 

Gadget Girl

Extraordinary
Contributing Artist
It's the very first line that is doing it:

mats = poser.Scene().WacroMaterials()

You're saying that mats is by definition whatever the WacroMaterials() are, regardless of where you are running the script. So if you wanted foainstace all the materials on the currently selected figure it would look like this:

mats = poser.Scene().CurrentFigure().Materials()

If you aren't using the Wacros you need to make another way to select which materials you are using.
 

3dcheapskate

Engaged
Thanks for the reply. Writing this response has helped clear things up in my mind - I think? :)

Yes to both your points.

The key is that as far back as the Poser 6 PoserPython Methods manual it says for WacroMaterials() - "Returns a list of materials on which a wacro is to be executed. This method is intended for use inside wacros; they should iterate over this list."

...but we all know that a button with "Don't Press Me" written on it is just asking to be pressed ! So I simply wondered what would happen if you used WacroMaterials() outside of its intended use !

Regarding your first point ("...mats is by definition whatever the WacroMaterials() are...") - what surprised me was that if I select one object and run a wacro from a wacro button using alt-click (i.e. do wacro on all materials of current object), then select a different object and run a script from my desktop that calls WacroMaterials(), it returns a list of all the materials in this newly selected object - I'd half-expected it return a list of all the materials in the original object. That's why I said that it appears to be some form of global currentMat/allMats flag (I had half-expected some form of global list of materials from the original object).

And on your second point ("...If you aren't using the Wacros you need to make another way to select which materials you are using...") you're absolutely right of course!

But there is a serious part to this. If your script is located in Wacros > UserDefined and you use WacroMaterials() it behaves in the same way as if you ran your script from the desktop. So the "...intended for use inside wacros" seems to be very specific - a wacro is only a wacro if it's run from one of the ten wacro buttons. If it's run from the User Defined drop-down at the bottom of the wacros then it's not a wacro (and of course you can't alt-click any of those scripts, which may be the key to it all)

So I'm fairly certain now that any user-defined wacro that uses WacroMaterials() needs to be attached to one of the ten wacro buttons in order for WacroMaterials to work as intended. If you simply run it from the User Defined drop-down the materials it acts on depend on how the last proper wacro was run. I'm thinking of adding an initial dialog to all my wacros that states this, with an option to cancel.

Does that make sense ?
 
Last edited:

3dcheapskate

Engaged
Thinking about it, I've got to the bottom of my concern:


If

a) somebody runs a wacro from the drop-down User Defined menu expecting it to work on just the current material

and

b) the 'wacro' uses 'WacroMaterials()'

and

c) the somebody had previously alt-clicked a wacro button (setting that imaginary global 'all-materials' flag)

then

d = a+b+c) they're going to get an unpleasant surprise when every material in the current object gets a new look !


Admittedly it's a rather unlikely combination of events, but in my my experience unlikely things happen more often than likely ones, especially when I'm at the controls! :D

Something like this would at least give the user an option to abort it (assuming they read dialogues - a rather rare quality! ;o)

mats = poser.Scene().WacroMaterials()
if mats:
goAhead = poser.DialogSimple.YesNo( len(mats) + " materials in the list ("+mats[0].Name()+", etc).\n\nContinue?")
if goAhead:
doMatStuff()
 
Top