Why can't you do the layout of huge file ? Is it a memory or a performance issue ? Assuming the binary file doesn't change each frame, could you do the layout once and cache the result ?
Kipt
But can't we have both methods? Yes, we can have the cake and eat it too (I call this cake programming). This does shove the problem to the usage code by some extent but it doesn't disable a good feature.
Do you mean you've figured out a way to not do two passes ? If so, can you explain ? What is different about the usage code ?
In the past weeks I've been working on UI code myself, trying to figure out a way to do layout of "complex-ish" things (mixing UI controls, text with wrapping, images and adding or removing things during the layout). I couldn't do it without making several passes, due in big part by a self imposed constraint that I don't want a frame of delay when the layout changes to reflect the change in scrollbar size and displayed content.
In my system (which is a week old and so probably has issues), I have 6 layout passes, some can be ran several times, some might be skipped.
- layout_pass_size_1
- layout_pass_scrollbar
- layout_pass_size_2
- layout_pass_input
- layout_pass_size_3
- layout_pass_draw
I start with
_size_1: compute the size and position of the content, if the content fits in the view rectangle, no scrollbar go to
_input.
If the content doesn't fit, you need a scrollbar, but since the scrollbar take part of the width, you need to restart the layout. I can early out the first pass as soon as the height is more than the view height (I'm not sure I'm actually doing this at the moment) and start
_size_1 again. If you've got a scrollbar, you need to know the height of the content to display the "elevator" with the right size so you need to finish
_size_1. Note that if I had scrollbars on the last frame, I will start doing the layout assuming I'll need scrollbars which is likely and avoids doing the first
_size_1 most of the time. I then move to
_scrollbar.
_scrollbar handle the view scrollbar input (it's a very short pass). If you move the scrollbar, the content that is in the view rectangle changes, and in my case I only generate "layout info" for things that are in the view, so if the view scrolls I also need to redo the layout after. So if the scrollbar was used, I got to
_size_2, other wise I go to
_input.
Nothing special in
_size_2 it just does the layout and moves to
_input.
_input: until here, the UI system did nothing when its functions where called. When
_input starts, it sets up the UI system to process mouse and keyboards inputs. In practice it's something like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 | if ( layout.pass == layout_pass_input ) {
ui_set_pass( ui, ui_pass_update );
} else if ( layout.pass == layout_pass_draw ) {
ui_set_pass( ui, ui_pass_draw );
} else {
ui_set_pass( ui, ui_pass_none );
}
...
/* ui_pass_update_draw is the default, and used when no layout is involved. */
b32 ui_button( ui_state_t* ui, ui_id_t id, rect2 rect, data_t label, u32 font_id ) {
b32 result = false;
if ( ui->pass == ui_pass_update_draw || ui->pass == ui_pass_update ) {
result = ui_button_update( ui, id, rect );
}
if ( ui->pass == ui_pass_update_draw || ui->pass == ui_pass_draw ) {
ui_button_draw( ui, id, rect, label, font_id );
}
return result;
}
|
If the
_input pass modifies the layout (for example checking a checkbox make new buttons appear), the control that modifies the layout needs to set a flag in the layout system to indicates that we need to redo a size pass (
_size_3) before drawing. Otherwise we go to
_draw.
Nothing special in
_size_3 it just does the layout and moves to
_draw.
_draw goes over layout items, and if they are in view, draws them.