• 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 ?

Karina

Member
(edited to add that this is actually a reply on how Snarly's "Scene Fixer" script works. I didn't see your other replies until after I posted mine)

I think the trick is with the nesting of the classes, and calling them from the main progranm routine.
Look at line #1941 pp:
It's where he calls the various classes and defines the parameters of the parent panel.

The solution to how he closes the panel is in the class "mainFrame()":
Line 1129 pp, "def __del__(self):" (just ignore the "clearEventCallback() if you don't need it)

I haven't seen such a method before (and obviously my way of simply using "self.Destroy()" seems to work too).

But maybe that's a solution if you have several panels declared?
Actually, I don't know. My Python-foo yet isn't mighty enough.

However, it might be worth analyzing the script to find out how he did it.

K
 

Ken1171

Esteemed
Contributing Artist
However, it might be worth analyzing the script to find out how he did it.

Yeah, I've noticed his code uses a certain odd way of doing things. WX looks quite similar to pyQT5 in many aspects, so I could quickly build my new GUI with WX because it "feels" like QT. The problem is that the programming API is new, like it was with Tkinter, and the way we use WX in Poser doesn't follow the rules, so the online documentation is useless. PhilC gives a lot of info on WX in Poser, but his Poser 8 code won't run in version 11. Most WX documentation seems ancient as well, like from 2005 or so. I could just remove the Exit button, and leave the "X" button from the title bar, since that already works anyway. I just wish I could see how that button was coded.

But what you said about the way the classes are structured might have something to do with this, in spite of what the WX documentation claims. I've noticed your code declares a class that extends wxFrame, and so did Snarlygribbly. The Poser documentation claims we shouldn't do that, and when I tried, it just crashed Poser right away at launch. There is something fishy there.
 

Ken1171

Esteemed
Contributing Artist
Used a single Poser cube primitive scattered to make a maze. :)

Maze.jpg
 

Ken1171

Esteemed
Contributing Artist
Ok, adjusted the code - now the props can be anywhere in the scene, and the pivot can also be anywhere. The tool will automatically handle everything on its own. :)
 

Ken1171

Esteemed
Contributing Artist
However, it might be worth analyzing the script to find out how he did it.

Ok, I have noticed one little critical difference in your wxPython class - you are extending wxFrame. Over here I am extending wxPanel, and that might be it. I understood we could NOT extend the wxFrame class in Poser, because its interface already does that. But your code works, so that must be it. That would also simplify things because we can use "self.Destroy()" if the class extends wxFrame, which is a top level class.
 

Karina

Member
Well, maybe it does work because I *didn't know* that it wasn't supposed to work.
Sometimes idiocy is a benefit :laugh:
But that's what I always loved: Finding out unusual ways of doing things.
You can see that in SASHA, and in a couple of other scripts I made (like the help files embedded and clickable from a library thumbnail etc.)

B.t.w., (and pardon the pun):
Your maze is simply a-maze-ing...
I'd really like to try the script once it's finished!

K
 

Ken1171

Esteemed
Contributing Artist
Thank you, Karina! The maze is SO simple to make with just a single cube. The script now also handles prop placement and pivot point adjustments automatically, so we no longer need to adjust those in advance. :)

The script itself seems ready and functional, but I still have this issue with closing the app, and I also want to add a few more features before I am done with it. I have rebuild the GUI, now starting with wxFrame, but I still can't close the app with it. I was sure that would make a difference based on what the wx documentation says, but "self.Destroy()" just crashes Poser back to the desktop. I have also tried the less aggressive "self.Close()", but in Poser that has no effect. In my stand alone tests, Close() actually terminates the app, but not in Poser.

Bummer that this is consuming so much time I could be using to add more features to it.
 

Karina

Member
I know this problem!

Most of the time I spend on a script is also to struggle with the classes and definitions, rather than working on the actual routines.
Like, it still escapes me how to implement a simple "Poser.CallBack" function if another figure or body part is selected...

Remember:
I'm not a professional coder!
All I can do now I learned from looking at code snippets, and a *LOT* of Google searches.

I started off (and was really a crack with it) "OMIKRON BASIC" for the "ATARI ST".
That was back in 1990-some!
It was a procedural language already, and had defs and functions already built-in.
PLUS you could declare global or local variables on the fly.
PLUS you could easily declare and use multi-dimensional arrays.
PLUS a string was a string, and you could easily manipulate it with just a few commands.
PLUS the interpreter in which you wrote your script was parsing for errors with every line you wrote, instead of spitting out cryptic error messages when running the script.
PLUS it indented automatically!!! :eek:
...
PLUS (...many more things I've probably forgotten...)

So with the way Python handles variables and arrays etc. and all the other Python quirks, I basically had to start from mark zero again :\

OK, rant finished :)

K
 

Ken1171

Esteemed
Contributing Artist
@Karina Haha yes, I know what you mean. I am a computer scientist, so programming comes naturally to me, BUT Python is a different animal with its own quirks that don't follow international industry programming rules and conventions. A lot of people claim Python is so easy to learn, but that only applies for very basic programming. For everything else, the way Python does its thing is obscure and unconventional. The years of experience I had with other languages did not help here, because Python doesn't follow standards. It also pushes some ways of doing things that are considered as "bad practices" in computer science. That means it makes it harder to do some things "properly" using scientific methodology from computer science.

Conversely, I can get things done with Python that would otherwise take much longer with other languages. It has pros and cons, and in general it can get the job done. All I can say is that this is a language that expects programmers to have a complete background in computer science, and years of experience with programming, so we can still use it "properly" as expected by its creator. You have to be professional, use proper scientific methodology, and have the discipline to avoid using Python "incorrectly", which may lead to a mess.

Languages like Java, ActionScript and C# prevent you from doing things incorrectly because the language was designed that way. Python has a different philosophy, claiming the language should not prevent programmers from doing ANYTHING, assuming they know what they are doing. As far as I can tell, from a computer science perspective, I believe that is a mistake, for we have decades of past programming to prove it. It's like selling a gun that has no safety lock, expecting everybody to use it responsibly. But that's just me. I use Python for everything now. It is what it is. :)
 

Ken1171

Esteemed
Contributing Artist
Here's an interesting test - there is a demo wxDemo.py in the Poser documentation that shows the bare bones of what it takes to create an empty WX frame in Poser, and write "Hello World" on it with a static text widget. I took this, and added a button to it. When we click it, it executes a single line "self.Destroy()".

Run the script from Poser, and it shows the panel as expected. Now click the button, and boom, instant Poser crash. Considering this is the sample code provided to demonstrate how to properly code wxPython in Poser, the way it was written MUST be correct. And yet, calling "self.Destroy()" from it crashes Poser right away.

Having that said, it appears this issue has nothing to do with how I write my code. If the WX demo code crashes, any program will crash if closed this way.
 

kobaltkween

Brilliant
Contributing Artist
Um, I'm using it and having no problem. Have been since I started my script. One sec and I'll check again. Yep, my script uses it without a problem on my updated P11.3 and always has previously.
 

Ken1171

Esteemed
Contributing Artist
@kobaltkween Thanks for the feedback. I have run another batch of tests, and one of them was stripping Karina's script down to bare bones, leaving only the top level panel. First thing that struck me was that it doesn't use ANY of the so-called "required" items, like creating WxAuiManager and GetManagedWindow objects to support Poser integration.

Below is the minimum bare app declaration according to the Poser documentation. I have used underscores to keep the indentation.

def main():
____man = poser.WxAuiManager()
____root = man.GetManagedWindow()
____win = App(root)
____man.AddPane(win, wx.aui.AuiPaneInfo().
________Caption("App Name").CaptionVisible().
________Float().Resizable().DestroyOnClose().
________FloatingSize(wx.Size(300,200)).
________CloseButton(True))
____info = man.GetPane(win)
____info.Show()
____man.Update()

Note the parts I have stressed above. The documentation claims these are the bare minimum to run WX in Poser. Now the big surprise - Karina's script didn't use ANY of these things, and it works. And what's most - it doesn't crash Poser to close the app.

This means I have been WASTING my time for DAYS trying to make this work by following the official documentation. Those 2 managers are not required, and they do cause Poser to crash when we close the script. Below is Karina's code to start the app that actually works:

def main():
____App(None, "App Name")


Yup, it's a single line, and has none of the WX managers "required" by Poser. When I close the app, it just works - no crashing. In other words, the official documentation is full of bull. It has misled me all the way here. I do believe that documentation was correct at some point, but it's certainly not in the current version.
 

Ken1171

Esteemed
Contributing Artist
Ok, deleted all these pesky Poser WX managers from my code, and guess what? The app doesn't crash Poser when closed anymore. My start-up code is now comprised of a single line, and I have removed all the extra imports. For some reason, the Scatter Tool performance has also increased, running faster then when controlled by these Poser WX managers. Not only that, but the close button now just closes the app, and my new title bar now has options to maximize and minimize the panel. This also makes it much easier to create interfaces with WX in Poser, since I no longer need these managers getting in the way.

With this out of the way, I can now go ahead and make the tool better. ^^

**UPDATE: These managers were used to allow the app to dock into Poser, and I am happy that doesn't happen anymore. Every time I tried to adjust the app's position, Poser kept trying to dock it, messing up my interface,
 
Last edited:

kobaltkween

Brilliant
Contributing Artist
Hmmmm. I _do_ have those in my code, and I still don't have a crash. Nor do I have the Poser-esque display style or docking. Haven't tried the code in the manual, though. At least not recently.

I will say that you seem to be making variables local to the method and not object properties. So I don't see how you could access them from other methods, and like the ones triggered by an event like a button push. But that's based on what you posted and not actually looking at your code.
 
Last edited:

Ken1171

Esteemed
Contributing Artist
@kobaltkween The code you see above is neither a class, nor a method. It's just procedural code to instantiate the main class and launch the app. The app is made of a single class that extends wxFrame, and contains all WX GUI definitions, including the events and respective bindings. I had to post the lunching code here because that's what was causing the issue. There was no issue with the app itself - everything worked fine, but I couldn't close the app without taking Poser down with it.

The only reason these managers are there is to allow docking the app into the Poser interface, which I don't want happening with this tool. Therefore removing that code has solved me 2 problems: the pesky docking, and the closing with crashes. There may be a way to use the managers and not crash Poser on exit, but I will look into that later when I actually want my app to be dockable. Not sure why, but removing the docking managers have also sped up the tool. It was dragging and chocking before, but now it's much fluid and faster. Maybe there is a price to pay for docking when it comes to performance.
 

parkdalegardener

Adventurous
Been following this with great interest here and elsewhere. Thank you for the WX GUI info or Karina. Doesn't matter. Thank you both. I;ll be first in line for this when complete.
 

Karina

Member
kobaltkween, parkdalegardener, please check your PMs.

@Ken1171:
Maybe there is a price to pay for docking when it comes to performance.

As I know Poser, the explanation for the loss of performance is probably because Poser spends all it's computing power constantly monitoring if one of your actions can be interpreted as "Dock this widget to a random place and mess up the GUI" :roflmao:

K
 

Karina

Member
Sorry, must have overlooked this post:

Here's an interesting test - there is a demo wxDemo.py in the Poser documentation that shows the bare bones of what it takes to create an empty WX frame in Poser, and write "Hello World" on it with a static text widget. I took this, and added a button to it. When we click it, it executes a single line "self.Destroy()".

Run the script from Poser, and it shows the panel as expected. Now click the button, and boom, instant Poser crash. Considering this is the sample code provided to demonstrate how to properly code wxPython in Poser, the way it was written MUST be correct. And yet, calling "self.Destroy()" from it crashes Poser right away.

Having that said, it appears this issue has nothing to do with how I write my code. If the WX demo code crashes, any program will crash if closed this way.

However, from what I know this example code was part of the Python documentation and samples at least since Poser 6!

Maybe it worked at that time, and the samples were just copied and re-copied to any new documentation without ever changing or testing it?

After all, the current Poser Python Methods Manual also still includes this gem:

"Python scripts are add-ons to Poser, and are supposed to be installed
into the application installation folder (ex: C:\Program
Files (x86)\Poser Software\Poser Pro 2012 for Windows, and Applications:
Poser Pro 2012 for Macintosh systems."


Right at the bottom of page 1 of the current version which shipped with P11! :laugh:

K
 

Ken1171

Esteemed
Contributing Artist
As I know Poser, the explanation for the loss of performance is probably because Poser spends all it's computing power constantly monitoring if one of your actions can be interpreted as "Dock this widget to a random place and mess up the GUI" :roflmao:

I suspect that might be the case as well. In addition, those constant attempts to dock everything annoys me when all I wanted was to reposition a panel. Once it gets auto-docked, it resizes everything around, and it won't undo the changes after undocked. That's why I prefer to remove docking from it altogether. The performance gain was just a bonus. :)

However, from what I know this example code was part of the Python documentation and samples at least since Poser 6!

Indeed, I think I came to that conclusion a few posts above as well. The WX integration must have changed, so I've got caught by such documentation inconsistencies for a few days until I realized something wasn't right here. I've just confirmed it with the example above, where even the demo code couldn't close the panel without taking Poser down with it. That was my confirmation.

However, KobaltKween has posted above that this is not always the case. There IS a way to keep the docking managers and close the panel properly, but I don't want to waste any more time on this since this tool will not use docking anyway. I know I will need to come back to this later, though, but for the time being, I want to move my project forward. :)

My current challenge is how to align a prop to the ground plane when it's morphed. The props can follow the shape and stay on top of it, but how do I align it to the surface? I know each vertex object has a corresponding normal, but under closer inspection, that is just another vertex object. If the prop is sitting on top of this vertex, can I use that normal to align it?
 

Ken1171

Esteemed
Contributing Artist
Um, I'm using it and having no problem. Have been since I started my script. One sec and I'll check again. Yep, my script uses it without a problem on my updated P11.3 and always has previously.

Thank you for the feedback. Could you show us the section where you launch the WX class, the part where the managers are declared? If it's the same as the code I have posted above (taken from the Poser documentation), then we have a mystery here.
 
Top