• 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

Instantiation Via (Poser) Geometry Swapping ?

Ken1171

Esteemed
Contributing Artist
Yet another issue with Tkinter - after I press a button that starts the scattering, it only depresses after execution of the callback function, and then it's state becomes reversed. And if I release the mouse button outside the button, it stays depressed afterwards. What a mess.... >___<
 

Karina

Member
Hello Ken:

I know that this may be something that cuts deeply, but:

Before you continue you should *really* consider abandoning tkInter and move to WxPython instead.
Most of the time it's only the programming of the UI that you need to relearn because there are significant differences.
OTOH it offers you ten-fold more control over how the UI looks than with tkInter.
The rest of the scripts' Python code needs to be adapted too, but that's no witchcraft.

AND:
Contrary to tkInter, wxPython will run on MACs too while tkInter has had some problems there AFAIK.

I'm also switching to wxPython currently, and it sure as hell is a lot which has to be coded in different ways.
But just the fact that I now can place my UI elements (down to the last pixel!) *exactly" where I want them to be makes all the learning worthwhile.
(and the buttons behave as they are supposed to XD )

Also, the declaration of global and local variables is a boon, though it is awfully cumbersome in wxPython because of all those "self." prefixes needed which makes the code hard to read.

Whatever you decide:
I think it's at least worth looking at what advantages wxPython has vs. tkInter.


def Karina(self, greetings):
greetings = greetings + 'care!'
return greetings

Message = self.Karina('Take')
print Message
#Take care!


P.S.:
How can I post code with indents here?
 

Ken1171

Esteemed
Contributing Artist
Before you continue you should *really* consider abandoning tkInter and move to WxPython instead.

Agree with everything you said - Tkinter sucks big time. I have already finished the program and the interface, but the buttons don't work as expected, and making GUI changes is a royal pain. My preferred GUI, and the one I am most proficient with is pyQT5, but that doesn't work with Poser, so I had to switch to TKinter. I didn't know it sucked so much, so now I will have to switch again.

Things I love about pyQT5:

* Multi-platform, runs everywhere. Even on some portable devices and smart TVs.
* Fully object-oriented. I work with classes, no scattered global variables.
* Is multi-threaded, great performance! Poser doesn't like this, though.
* Is quick and easy to create GUIs, and also easy to modify them afterwards.

I will take a look on wxPython and see how this one is. It's the last chance, since the only other choice is ancient Tkinter. Wish me luck! ^^
 

Karina

Member
b.t.w,:
wxPython also uses classes.

You can define the whole GUI (or widget as it's called) as a class, and then either include defs in the class itself, or branch to defs outside the class.

I prefer the latter because I'm used to it:
IMO, to have different script blocks for the UI and for the code which does the actual work improves the readability of a script.
I use Notepad++ to write my code, which allows me to collapse parts of the code not currently needed, so that I mustn't scroll through thousands of lines of currently irrelevant code.
But that is up to personal taste.

What I absolutely like in wxPython is the flexibility in designing the GUI:
No more need to calculate frames, grids and columns to arrange your buttons!
Just input coordinates and width/heights when spawning them.
Then "bind" them so Python knows which element you clicked on, and branch to the relevant subroutine (def).
Everything else will happen "avtomatisheskiy" ;), unless you explicitly code it else.

All my old scripts that came with SASHA-16 and my "Karina's Tool Box" still use tkInter, and they have so many glitches that I plan to rewrite them in wxPython if I have the time.

One (but not yet the major issues I had with tkInter) was that if a script does more complex changes, and I want to display a simple message like "Script finished", the message pops up ***before*** the script ever sets to work!!!
...Mythical mysteries of tkInter... :D

K
 

Ken1171

Esteemed
Contributing Artist
I have been learning wxPython and... it looks a LOT like pyQT5, which I am already familiar with. That means I won't be taking long to get used to it. The only thing concerning me was when I wrote some code to create a simple frame (no widgets), it worked in Python 3, but... nothing happens in Python 2. I have tried it inside and outside of Poser, and the same happens. It doesn't give me an error message or anything - just nothing happens. No frame shows up in Python 2.7. I have to figure this out, and I will look into that once I am free from my current project.
 

Ken1171

Esteemed
Contributing Artist
Taking a closer look, it appears that Poser has special requirements to use wxPython GUI that is different from what we would normally do elsewhere. For starters, it takes a different root Frame node, and is requires Poser's own UI manager to integrate the wx widgets with its own main loop. That's why my standard code wxPython didn't work in Poser. Something to get used to.
 

Ken1171

Esteemed
Contributing Artist
Ok, I understood it now. Poser uses wxPython on its own interface, so a default root frame and main loop already exist. It's extending an existing interface instead of making a new one. We have to get the root frame and main loop from Poser first, and then use them in our custom interface.

What that means is that, normally, a wxPython GUI would start with a frame, but in Poser that already exists, so we have to start with a panel instead. Another thing is that, normally, we would have to start a main loop, but in Poser it's already running, so we just have to get a reference to it. There is also the fact that we cannot end the main loop, so things are a little different.

I get it now.
 

3dcheapskate

Busy Bee
On the (very) rare occasions that I write any PoserPython UI stuff nowadays I personally prefer poser.dialogSimple.YesNo(). Lots of them, one after another, with the occasional poser.dialogSimple.MessageBox() to provide a dash of variety.

And if I'm in rakish devil-may-care mood, perhaps I'll even throw in a poser.dialogSimple.AskMenu() :devil"

I think it's because I really enjoy trying to reduce the length of any text I want to display so that it fits into the darn dialog box !
 

Karina

Member
AH, good!

Now that I have you here both (and, hopefully, your attention?), may I ask you both a favour?

I've just finshed my work on two scripts today on which I was working while trying to learn the self.darn() wxPython:

It's:

- A:
A script to save facial expressions from a variety of figures, including Dawn, PE, Polina, LaFemme, V4 & M4, and (of course!) SASHA-16.
It is designed to finally write expression .fc2 files which don't reset the face to default as Poser does, and also doesn't include tons of irrelevant legacy code.
Plus it offers some other useful options.

- B:
A script that lets you export morphs and save them as regular .pz2 injections without the need for the dreaded .PMD files which Poser insists on.
Again, with several options of how to save the morph(s).

I'm looking for BETA testers. Would you like?
If so just let me know and I'll send you a link to the download.

The reason why I don't publish them in the open is purely selfish:
I want me to spare the hassle of having to deal with people who download the public BETA (mostly those who download everything clickable...), and then come back complaining without giving any real feedback at all (well, except saying they tried it with "Genesis-whatevernumber" - sigh!!).

I want to spare me that, thus my question to you two because I know you're quite proficient in scripting, and obviously much more advanced than me.
And from what I've seen from your work, you're also good at coming up with unusual solutions, and you're able to think "out of the ordinary". (?expression?)

I'ld be happy if you could help me with screening the scripts.
This in particular because I don't have the latest versions of Dawn, PE, Pauline, and LaFemme2.

Thank you!

K


P.S.:
This is *NOT* a commercial project!
The scripts will be released as public domain once they are hardened enough against misuse so that even the biggest BDU wont break the script (in the first attempt, at least)...
 

Karina

Member
ADDENDUM @Ken 1171.
Ok, I understood it now. Poser uses wxPython on its own interface, so a default root frame and main loop already exist. It's extending an existing interface instead of making a new one. We have to get the root frame and main loop from Poser first, and then use them in our custom interface.

What that means is that, normally, a wxPython GUI would start with a frame, but in Poser that already exists, so we have to start with a panel instead. Another thing is that, normally, we would have to start a main loop, but in Poser it's already running, so we just have to get a reference to it. There is also the fact that we cannot end the main loop, so things are a little different.

I get it now.
Yes that's correct.

In fact you should *never* create your own frame when using PoserPython!
Let PP do the work instead.
Just call PP, declare the GUI, and all will be well.

Because every frame you declare outside PoserPython wouldn't be recognized by Poser and in the Worst Case Scenatio, will crash Poser beyond anything else than a kill by the Task Manager...
Took me some time to understand why some code snippets I found wouldn't work in Poser.
But once you've understood how it works, it's even simpler, compared to having to create and manage your own frames etc.

Just declare a Poser frame and build your GUI.
Poser will do the rest of the work for you.

K
 

Ken1171

Esteemed
Contributing Artist
On the (very) rare occasions that I write any PoserPython UI stuff nowadays I personally prefer poser.dialogSimple.YesNo(). Lots of them, one after another, with the occasional poser.dialogSimple.MessageBox() to provide a dash of variety.

I used to do things that way before I've learned Python, but most of my scripts require more elaborate GUIs to work properly, so that won't work for me anymore. For example, the scattering tool needs quite a variety of widgets to configure the process properly. A proper GUI is required. For simpler things, those Poser dialogs will do. :)

I'ld be happy if you could help me with screening the scripts.
This in particular because I don't have the latest versions of Dawn, PE, Pauline, and LaFemme2.

Sure, I can help you test the scripts, but I use mainly Dawn and V4. I think I have Pauline and LaFemme installed, though. Not sure what version, because I don't use them in my pipeline.

BTW, Poser only creates PMDs if you want it to. You can disable this completely in the configuration panel (last tab on the right), and from that on, all saves will embed the morphs. In my workflow, I only create PMDs for INJ/REM morph injections, and embed for everything else. On the other hand, I leave PMD on by default to make saving/loading scenes faster - much, much faster, actually.

One of my feature suggestions to SMS was to allow selecting if we want to use PMDs straight from the saving to library dialogs. This way we don't have to change Poser's global settings just to save a particular item to the library, and then remember to change it back afterwards.

In fact you should *never* create your own frame when using PoserPython!

Yes, I have learned this the "hard" way. LOL
 

Ken1171

Esteemed
Contributing Artist
Ok, I made the new GUI with wxPython. That was the easy part. Now I need to code the integration with my scatter tool module, but the documentation sucks. The Poser documentation just claims that wxPython exists, and it requires unicode strings - Is that it? What a joke...

How do I close my custom WX window? I saw some examples from PhilC, and his code for Poser 8 doesn't work. All he did was to call "self.Destroy" on the exit button click event, and that just removes all widgets - it won't close the panel. I end up with an empty panel which cannot be closed.

Any hints?
 

Karina

Member
To answer your last question first:

The Poser documentation *IS* a joke indeed; most I learned about wxPython I learned from Google searches, or from looking at code examples just to see how it actually works.
You're right about the unicode strings. Look here:
UnicodeBuild - wxPyWiki

I too use self.Destroy() to terminate the widgets.

I also ended up with some unresponsive panels in the beginning.
Mostly it happened when a program runtime error occured and the panel couldn't terminate properly.
My "brute force" solution was to close and restart Poser...


About PMDs:
-----------

Yes, the checkbox in the General Preferences stops Poser from using PMDs *on normal saves*.

Problem is:

If you click "File:Export:Morph Injection" from the menu, Poser will inevitably and stubbornly create a PMD file for the morph, and there's no way to stop this.

Even if you only want to export *one* single small morph in only *one* body part, you end up with an associated PMD file, and *not* with embedded morph data in the .pz2

To make matters worse:

In the .pz2 the PMD is referenced by a path to the *current* folder, e.g. "runtime\libraries\pose\thisFolder\myMorph.pmd"
So once you change your runtime folder structure, or copy the "myMorph.cr2" to a different folder, the path becomes invalid and that was it. That's probably also the reason for the massive loss of data I had when starting with Poser.
It's a bit like boobytrapping your backyard with mines and then mislaying the plan *where* you laid them...

Plus:
The Poser export is (as usual) very slow and cumbersome to use.
It takes about ten seconds to even make the widget pop up, and then it's the usual dreaded "Select objects" widget which you have to scroll through endlessly just to find that *one* morph you want to export.

That's why I wrote my script.

But you can test it for yourself.
I'll upload it in a few hours and send you the link via sitemail(PM). Just too late (or rather: too early (04:30 here))

And maybe, if you look at it's structure, you can also see how I implemented the GUI.
Feel free to copy it!
All you need to do is to change it's size,replace the buttons etc. with your own, and then add the rest of your own code.

For me, a single example code replaces a hundred tutorials with esoteric mumbo-jumbo descriptions.
That's how I learned coding back then.

K
 

Ken1171

Esteemed
Contributing Artist
If you click "File:Export:Morph Injection" from the menu, Poser will inevitably and stubbornly create a PMD file for the morph, and there's no way to stop this.

Ohh, maybe that's why I haven't noticed this before. I always include PMDs when creating morph injections. It's more memory efficient (and loads faster) when we apply the same morph to different copies of the same figure, because they will all share the same morphs. So much that Rendo has changed the default scene to now used PMDs because it loads faster in the new 11.3 update. I have always liked this side of PMDs. Conversely, morph injections are the only case when I would want to have PMD files generated, so it's not for everything.

In the .pz2 the PMD is referenced by a path to the *current* folder, e.g. "runtime\libraries\pose\thisFolder\myMorph.pmd"
So once you change your runtime folder structure, or copy the "myMorph.cr2" to a different folder, the path becomes invalid and that was it.

Yes, that's a bummer, but you can easily solve that by deleting the relative path, leaving only the PMD file name. Then you can move the files around, and it will always work from anywhere. I do this in all of my products.

The Poser export is (as usual) very slow and cumbersome to use.
It takes about ten seconds to even make the widget pop up, and then it's the usual dreaded "Select objects" widget which you have to scroll through endlessly just to find that *one* morph you want to export.

I couldn't agree more. I have suggested SMS to add a filter box to this dialog, so we can get to the part we want faster. It's a dread to find anything when we are facing ALL morphs in a single list. I don't know how this would be done, but it would also be helpful to separate body and head morphs in that list, because we don't want to copy head morphs to clothing, or body morphs to a head.

I have just finished coding my "Scatter Tool", now with a wxPython interface. Somehow it now runs faster, and the interface behaves just as expected. I was having all sorts of inexplicable interface glitches with TKinter, not to mention the GUI dragged with low performance. WX seems much better, faster, it offers more widgets, and these have more options to play with. This is the new interface, and everything works great - better than with TKinter. When we resize the panel, all elements scale nicely with it. At least this part Tkinter could do fine as well.

I always separate GUI from behavior, so I could easily change the whole interface without modifying the scatter tool code at all. It's the same scatter module for either TKinter or wxPython. That's the time when having a computer science degree pays off. ^___^

GUI.jpg

I made this "dark" theme for the interface, but I couldn't figure out how to recolor the button borders. I could only find the background and foreground colors, but nothing about borders. Couldn't find that info online either. So the buttons have the ugly white border at the moment. Funny that PhilC's code only uses these back and fore colors, and his screenshots don't have the white borders. Maybe things have changed since Poser 8, and now the buttons have more skinning areas?

The only bummer is that closing the app with self.Destroy() consistently ends up with a blank panel, and soon after Poser crashes. Clicking the "X" button from the title bar closes properly, but I don't know how that was coded. All examples I have seen so far close with self.Destroy, and so far that has been a no-no in all cases. Poser doesn't like that. There must be another way.

Calling Destroy() removes all widgets from my panel, but it doesn't terminate the app itself. It crashes Poser instead, and this ALWAYS happens, so it's not a bug. It would make sense to end a WX app with self.Destroy() if we created the frame ourselves, but that is not possible in Poser. This is why WX code from the web will be useless. Outside of Poser, WX will not even allow an app to be created without a Frame on the top.

To kill a WX app starting from a wxPanel (and not a wxFrame) probably requires a different kind of termination. We just don't know what it is.
 
Last edited:

Ken1171

Esteemed
Contributing Artist
Scattering 2 cubes (Poser primitives) to make a city. Was debugging the placement algorithm to make sure it never places 2 objects in the same place. It keeps track as long as it's in the same session. Objects can be added and mass removed based on their original name. In this case, I have 2 cubes with different names, so we can wipe each of them out with a single click. This is useful when we didn't like the scattering placement of a new object, and we can remove only those and try again without affecting the others. They can be added and removed in any order.

City1.jpg
 

KageRyu

Lost Mad Soul
Contributing Artist
An option to use a random assortment of objects or props from a directory or list would be amazing...especially for cities, ruins, forests, etc...
 

3dcheapskate

Busy Bee
I'm looking for BETA testers. Would you like?
I'm generally happy to help, but I don't think I'd be much use for the two scripts you mention.
(P.S. I'm assuming you were referring to me when you said "you two" as the request was just below my post. But the "because I know you're quite proficient in scripting, and obviously much more advanced than me" confused me - nobody who's looked at any code I've written would say that ! :roflmao:


- A:
A script to save facial expressions from a variety of figures, including Dawn, PE, Polina, LaFemme, V4 & M4, and (of course!) SASHA-16.
It is designed to finally write expression .fc2 files which don't reset the face to default as Poser does, and also doesn't include tons of irrelevant legacy code.
Plus it offers some other useful options.
I've never been aware of FC2 files resetting other non-expression facial morphs, which is what I assume you're referring to.
I don't think I've ever saved an FC2 file, and I rarely load the ones I've picked up - they're mostly crap. On the whole I prefer to twiddle the dials myself and produce my own crappy expressions ! ;)
So without really being aware of the problem I'm not really a good person to test a solution.

- B:
A script that lets you export morphs and save them as regular .pz2 injections without the need for the dreaded .PMD files which Poser insists on.
Again, with several options of how to save the morph(s).
Can't really help with this one. The only time I've ever really encountered PMD files was when I specifically wanted to create one for my first book row, so I must have Poser set up to never use them.
So once again, without really being aware of the problem I'm not really a good person to test a solution.
 

3dcheapskate

Busy Bee
To kill a WX app starting from a wxPanel (and not a wxFrame) probably requires a different kind of termination. We just don't know what it is.

SnarlyGribbly's UIs were wxPython - I've just had a look at SceneFixer.py but can't work out where or how it closes !
 

Ken1171

Esteemed
Contributing Artist
SnarlyGribbly's UIs were wxPython - I've just had a look at SceneFixer.py but can't work out where or how it closes !

I took a look on his "Snow Machine 2" script, where he uses WX and the form closes from an "Exit" button and also from a main menu option. In both of them, the event handler was left blank, so I have no idea how the form closes. One thing I've noticed, though, is that he has only used "Destroy()" to close dialogs, NOT the main WX app. That kind of confirms my suspicions that we shouldn't use that for this. Every time I did it, Poser crashed.

So now I have 2 example codes: one from PhilC (ancient from Poser 8), and one from Snarlygribbly. PhilC used Destroy(), but his code no longer runs in Poser 11. Snarlygribbly didn't use anything, so I am kind of perplexed. Over here, my event for clothing the panel is also blank, and that, obviously, won't close anything.

HOW do we close a WX app???
 

Ken1171

Esteemed
Contributing Artist
An option to use a random assortment of objects or props from a directory or list would be amazing...especially for cities, ruins, forests, etc...

They way I did it with the Scatter Tool is like this:

* The list on the left shows all available props on the scene. You have to load them and size them first. They have to be centered, and with the pivot point at the ground. Many props are placed at different places by default, so by now I have to manually center them and fix the pivot point. I am thinking of ways to automate this too.

* Pick a prop from the list, set the number of copies you want, and configure the variations parameters.

* Every time you press "Scatter selected", the tool will spread the object across the ground plane using your settings. It keeps track of where things are placed, so each will be placed at a different location (not on top of each other).

* You can adjust the params and keep pressing the scatter button to add more. At any time, you can press "Remove Selected", and this will remove all instances of the currently selected prop from the list. This is based on object name, not the geometry. so we can scatter the same object with different textures or properties separately from other props if they have a different name. That's how I did it with the "city" from above. It's the same cube with 2 different textures and different names.

* The tool automatically adds a prefix to each prop it creates, so they won't interfere with existing objects in your scene. The interface allows you to change this prefix if you like.

* You can keep adding/removing objects in any order until you are happy with it, or you run out of space in the plane. The tool will automatically stop when that happens, and let you know with a message.

* You can manually adjust the position of any prop at any time to fit your scene.

That's about it in a nutshell. ^^
 
Top