[Scummvm-devel] New GUI thoughts in the Wiki

Max Horn max at quendi.de
Sat Nov 19 09:05:15 CET 2005


Am 19.11.2005 um 15:50 schrieb Marcus Comstedt:

>
> Max Horn <max at quendi.de> writes:
>
> [...]
>> For briefness I'll just talk about DLE's in the following :-).
>>
>> in OSystem:
>>     DLE_ID appendElementToDisplayList(DLE e);
>                                         ^^^^^
>                                         Should probably be DLE& e  :)

No, I wrote DLE on purpose -- because this is just a *sketch* and it  
just means to roughly outline which data would be passed where,  
etc.. :-). Whether to use DLE, const DLE &, DLE & or DLE * -- we'll  
see :-)

That said, we probably should document the result of this discussion  
in the Wiki, too :-).


[...]

> For this dirty-flag to be meaningful, you'd have to be able to combine
> multiple DL modifications without an incremental redraw in between.
> Otherwise you can just replace "mark as dirty" with "redraw".  But
> I suppose we'd have some kind of transaction system similar to what
> we have today (everything done between two copyRectToOverlay() goes to
> the screen as one unit).

The dirty flag is just that -- a dirty flag. It's a single bit/bool  
present for every DLE :-). There is not even a need for  
"transactions" here. Rather, the display list would probably  
processed inside updateScreen(). Just as you guessed (i.e. similar to  
copyRectToOverlay / copyRectToScreen).


>
>> 6) If the GUI is designed carefully as to reduce overlap, this means
>> we get a relatively low redraw count
>> 7) Making it possible to modify a DLE in-place could be used to speed
>> up in-place modifications. Typical example: A button which switches
>> between active, clicked, and disabled. By using
>> updateElementInDisplayList, ideally only the button has to be redrawn
>> (assuming nothing else covers it); if we handle text via DLEs, too,
>> then the button and the text have to be redraw, which is still quite
>> moderate.
>
> Yes, if you avoid exposing the background, you'll save a lot with the
> algorithm above.  However, while the updateElementInDisplayList would
> be ok for button, maybe we need to find a more general solution.
> Consider a slider for example.

Indeed. I thought about sliders/scrollbars right after sending my  
mail :-).


>     +------------------------------
>     | A
>     |   +-----------------+
>     |   | B          |C|  |
>     |   +-----------------+
>
> A is the GUI background, which is large and covered by lots of GUI
> elements.  If it becomes dirty, we'll have to redraw everything.
> B is the slider background, which is much smaller, and only covered by
> C, the slider knob.

Indeed.

> If we drag the knob, we expose a portion of B which was not previously
> visible, so it needs to be redrawn anyway (updateElementInDisplayList
> will not help us here).  However, if the check described in 4) above
> only checks the bounding boxes, it will determine that A was also
> covered by C, and flag it as dirty.  Unless B is semi-transparent,
> that's not really necessary.  So we can tweak step 4) a bit: If, when
> scanning the DL for DLEs that were covered by the removed DLE, we find
> one which actually has the _entire_ bounding box of the removed DLE
> inside its own bounding box (and which is not semi-transparent), then
> we can terminate the scan (after marking that DLE, and those covering
> it, as dirty) and ignore the bounding boxes of any "deeper" DLEs.
> Since C is completely contained in B, only B and C would be redrawn
> when the knob moves.

And since the DL is sorted in z-order, we can just stop looking  
through the DL. Neat.

In fact, the nature of our usage of the DL (for a GUI) means that  
almost all (if not all) pairs of DLEs will either not overlap at all,  
or one of the two will be completely contained in the other. So it  
makes a lot of sense to take advantage of this to get efficient  
algorithms and efficient redrawing.

So at first, this all sounds like a very good plan. And I like it.  
However, it's not quite as simple as it sounds here... because not  
all DLEs are covering their full area. Transparency effects etc.  
partially break this approach. This is most obvious for a "text DLE",  
but also for bitmaps, which usually would employ transparency at the  
corners (think rounded rectangles, as seen in the concept drafts of  
the GUI design).

One possible solution would be to not allow transparency. If we  
restrict ourselves to single colored backgrounds, we can achieve this  
by adding a "background_color" attribute to every DLE, and when  
redrawing it (or portions of it), the corresponding area is first  
filled with the background color. Or for bitmaps, we could simply not  
allow transparency for them.

As long as we only allow 1 bit transparency, we could also rely on  
the client code to take care of proper usage itself. E.g. for  
buttons, the pressed / non-pressed versions would precisely cover  
each other anyway, so no harm would be done if we ignored any  
transparency issues for them. The story is a bit different when full  
8 bit alpha blending is used, of course, because we don't want to  
alpha blend a button with an older version of itself.




[... explanation how to get rid of updateElementInDisplayList by  
using insertElementInDisplayListBefore ...]

Alternate suggestion: We keep updateElementInDisplayList, but  
implement it by using insertElementInDisplayListBefore as you  
described. This way we can drop the restrictions imposed on it. If  
the size / position or type of the DLE change this way,
Makes sense, too. We could still keep updateElementInDisplayList  
around for convenience, implementing it using  
insertElementInDisplayListBefore.


Cheers,
Max




More information about the Scummvm-devel mailing list