[Bf-committers] Blender.UI? (Re: properties per datablock & python)

Mathias Panzenböck grosser.meister.morti at gmx.net
Sun May 18 17:34:15 CEST 2008


Toni Alatalo schrieb:
> Mathias Panzenböck kirjoitti:
>> I wrote a little abstraction layer for blenders GUI functionality. I think the python 
>> API to draw GUIs is very ugly. My abstraction layer makes it much more object 
>> oriented and declarative (you create a button and it will be displayed until you 
>>   
> 
> you must be about the hundredth person to do that :(
> 
> which if course means that what you say is true, Draw is not a nice way 
> to make UIs, which is why a large part of *many* scripts has for long 
> been their own UI wrapper thing over the bpython stuff. some of those 
> have been packaged as libs to be nicely reusable, one such was ScriptUI 
> by someone (sorry I don't remember who) which I've reused in some 
> scripts long ago.

By me! It was written by me! ;)
But I'm unsatisfied with it so I wrote a new one. And I was unsatisfied with that so 
I wrote a new one... maybe most of the 100 wrappers are done by me? :P (No, only 
about 3) The newest is not really released and it's not in a release able state. I 
wrote a new wrapper that is more easy to use than ScriptUI for teh delolition scripts 
GUI and then I improved that (lots of refactoring) for the ID Properties Editor.

I know how a good API should feel as an API-user. But I'm obviously not good enough 
to write a perfect API. I always feel dissatisfied with it. I think the "listener" 
approach I used in my new wrapper is better than the method overloading, because when 
you overload a method what happens when you derive a new widget and overload the 
method again? To register and unregister listeners is a nice thing. I think Javas 
SWING does it in a similar way. But what if you register a method of the Widget 
itself as listener? Then you get a cyclic reference -> memory leak. Therefore I wrote 
a WeakListener that uses weakrefs. But it is ugly that the API user has to know when 
to use this. I think the add*Listener methods should do a cycle test, but how to do 
this in a reliable manner? You can add functions, static methods, normal methods, 
lambdas an callable objects as listeners. This all has to be taken into account and 
there has to be special code for either case. I clearly do not have time for this. 
Maybe in the summer break.

And there is another problem: my Widgets do not use MVC, which is bad. Very bad. 
Partially this is because the Blender.Draw things are not MVC based. Without MVC 
there is a LOT of redundant data. E.g. in the ID Properties Editor all values are 
stored in the ID properties AND in the GUI. I have to keep them in sync somehow. If 
some other script changes an ID property my GUI does not know that (lost updates).

Another think what my wrapper(s) don't do is clipping of child widgets in parent 
widgets (so childes my "leak" over the borders of a container widget). Well, how 
should I do that with the given functionality of Blender.Draw anyway?

> i've wished and suggested for long that someone would 
> take a look at those libs and perhaps put together something that would 
> have been included in the official distro, as e.g. Blender.UI module (i 
> think it would have been fine as a py wrapper over the old c stuff, 
> althought i'm sure people would have also liked to get rid of some old 
> nastyness in the Draw and Window modules). but again wishing and 
> suggesting don't make things happen, and i guess i didn't have much 
> interest in working there myself (have for long been quite uninterested 
> in wimp guis. but that's just me being stupid :).
> 
> well, luckily 2.50 is AFAIK now coming up with the tool API etc. so we 
> should finally get to good shape there. so i guess the point is that 
> everyone who wants to get a nice ui api should pay attention to the work 
> there, i think having written such an abstraction layer yourself you 
> have very good base for critical review etc. of the coming 2.50 
> architecture.
> 
> ~Toni

Yes, I hope 2.50 will have a descent GUI API. At least get rid of the draw method 
(though still allow draw hooks) and the manual (button) event filtering. Nowadays the 
Blender.Draw things have callback hooks for the events. But for a real GUI API not 
only the "action" event should be reported. I think events like the following would 
be nice for more sophisticatedly GUIs:
onchange, onclick, ondblclick, onfocus, onblur (lost focus), onmousedown, 
onmousemove, onmouseout, onmouseover, onmouseup, onscroll (?), onkeydown, onkeyup, 
onkeypress

The mouse events I hacked into my new wrapper by manually dispatching the event in 
python. So on every mouse move the Widget-tree is searched for possible matching 
widgets. This can for sure be optimized. I think just to move this code (that is 
executed on every mouse move!) into C would improve performance. On the other hand my 
code seems to be fast enough on my machine. :)


	-panzi


More information about the Bf-committers mailing list