bagginsbill opened this issue on Mar 12, 2008 · 6 posts
bagginsbill posted Wed, 12 March 2008 at 5:41 PM
Hello Poser Pythonistas!
I think many of us are simultaneously working on the same thing - a better way to do GUI stuff for Poser Python plugins.
I long ago rejected the Tk stuff - I'm just not interested in that ugliness.
I want to have a rich, interactive, easy-to-develop GUI experience to be included with my scripts, such as Matmatic 2.0, Parmatic, my as-yet-unfinished Versatile Shader System, my "Carpenter" wood scripts, my new "Geomatic" script (what Matmatic did for procedural materials, Geomatic does for procedurally generated geometry) and a few other ideas I've got. Some requirements:
In the past, I was pretty happy with WxPython, which could satisfy most of those, but my understanding is that it isn't straightforward for a user to install onto Poser Python. Thus it breaks rule 4.
I've done a lot of experimenting and have come up with something I quite like at the moment. I made a Poser Python script that acts like an application server, something similar to a Java-based server. But instead of Java, you script it with Python. I've produced a pretty nice library of components to go with it. This system, I call Paser (Poser Application Server). I intend to make Paser open source - meaning you all get the source code and can contribute extensions and improvements to the framework.
To add a new application to Paser, you write a Python script and put it in the Paser/apps folder. Paser has a built-in system for detecting installed scripts, and incorporating them into its "menu" database.
For any development environment, one must present the "Hello World" application. Here is the Paser version:
def main(): print "Hello World"
Done! If you put that in a test.py file in the Poser apps folder (or some subfolder) it will instantly be available. You then click a link on the Paser Main Menu page to run it.
Basically, when you hit the Paser server with something like /test.py, it finds the file, compiles it if it hasn't yet been compiled, sets up some initial state, and calls your "main" method. Anything you print will be sent in the response, which by default is assumed to be an HTML document. You can, however, instruct Paser that you're doing some other kind of document and then write the data any way you like.
To get it to call other methods, you say /test.py?op=foo, where foo is the name of the method you want to call.
So I can write:
def main(): print 'Click me to call Foo'
def foo(): print '
Here, main made a link which upon clicking, calls foo.
Now it can get pretty annoying to type and print all that HTML markup, so I made an HTML "emitter" class library that takes care of all that crapola for you.
Using the library, you write:
from html import *
def main(): return Link("Click me to call Foo").clicks('foo')
def foo(): return Emitter(H1("Foo!"), "You called Foo successfully.")
There's a lot more to it, but that's the basics. Additional parameters can be passed in the URL and they are easily pulled out by the python.
Then I started to play with AJAX. Using an AJAX library, I can make complicated widgets inside the page, and have those widgets send me events in real time, back to my python code. I can also make the python code generate new contents that get sent back to the page, which can replace all or part of what is on the screen.
I have a system of "delegate" objects that take care of all the plumbing for this sort of thing. So for example, if I want to iterate over all poser lights and make a slider that controls the intensity for each, in real time, I can do something like this (not exact yet - still working out details):
def main():
p = Panel()
for light in poser.Scene().Lights():
p << [ QHTML(light.Name()), Slider().invoke(setLightIntensity, light, Callback.value), BR]
return p
def setLightIntensity(light, value):
light.Parameter("Intensity").SetValue(value)
The QHTML function just quotes any characters from the light name that might cause problems in HTML.
The Slider is a class that knows about the Javascript library I've got on the client side in the browser. It makes a true slider.
The "invoke" method specifies that when the slider is updated by the user, I want it to call the setLightIntensity method, passing the specified light as an argument.
The object "Callback" is special. Asking for .value on it returns a callback object that later will be substituted with the URL 'value=' parameter. So my method will also be passed the value of the slider.
This is pretty cool stuff, and very easy to code.
I've been exploring the various free Ajax libraries: prototype, jquery, dojo, and mootools.
Of the four, I think I like mootools best. So my first question is - any opinions?
Now on the flip side, lately I've been doing a lot of .NET/XAML/C#/IronPython stuff, and I gotta tell you it is flipping awesome! So I'm looking into Silverlight - which supposedly would let me use all the full-blown WPF user interface stuff I now love, but it will work IN ALMOST ANY BROWSER, and it will work ON A MAC!!!!!!
So - second question. Any opinions on Silverlight? Any MAC users - have you run it - does it really f'ing work? I mean, if I make a rich GUI with listboxes, tree views, images, animations, blah blah, you see it all correctly on your MAC?
Because I gotta tell you, the Javascript/AJAX stuff is cool and all, but its hard to work with. Debugging is difficult, the language ain't that great, and the widgets are not truly object oriented in the full sense of the word. If I can code up the UI behavior in XAML and IronPython and it works everywhere, and just handle the callbacks inside Poser Python as RPC calls, well I think I'd be pretty happy with that.
Renderosity forum reply notifications are wonky. If I read a follow-up in a thread, but I don't myself reply, then notifications no longer happen AT ALL on that thread. So if I seem to be ignoring a question, that's why. (Updated September 23, 2019)