20 Comments
May 23, 2022·edited May 23, 2022

This posts are amazing, thanks!

When you talked about features as widget flags, I thought it to be limiting: the library users can only create a new widget which has at most N features, but what if they need a new one? In this way, if I'm not missing something, they should wait for the library developers to add it. While it's certainly better than the WidgetKind, maybe we could push the abstraction further. In the Molly Rocket forum (https://web.archive.org/web/20070825122349/http://www.mollyrocket.com/forums/viewtopic.php?t=134&postdays=0&postorder=asc&start=30&sid=9680eeedbe87034741d936cbfe319f57) Casey talked about how to customise a button, generally created through doButton():

> there'd be three calls, typically: DrawButton(), ButtonBehavior(), and DoButton() which calls them both. If you want to draw it differently, you just replace the call to DoButton() with a call to ButtonBehavior(), and draw the button yourself. That's all there is to it.

What do you think?

Expand full comment

Thanks for this series of posts on UI. It will be my point of reference for my next UI-related project.

I have one question regarding the UI_Comm struct: what is the rational behind including mouse pos and drag_delta in it? Since those two should remain fixed across the whole frame, I assume you can store them as global states, just like any other input states? What am I missing here?

Expand full comment

Great post. There's one (probably quite simple) problem I can't see how to implement this way - how do encode a parent that has a border? The size of that parent node, let's say is 200x200px and it has a 5px border - there's no "inner" size or coords there, and I'm wondering how to implement such a thing. Would you encode a bordered parent as 2 widgets? One that draws its background and another nested inside that is offset somehow using some new variant of UI_SizeKind? With the example code the way it is, I can't see how this fits in. Another way would be to have a code path in the layout code that "shrinks" children inside bordered components but that seems like it would invite further problems with the other layout code.

Expand full comment

So you basically discovered the div

Expand full comment

Once again, thank you for the great series. Working through your suggestions, I should be able to resolve a number of ugly workarounds resulting from a more traditional IMGUI implementation.

This may be a dumb question, but shouldn't UICommFromUIWidget be taking some sort of mouse/keyboard state input (say, from the OS/platform) for hit testing against the rect? I'm assuming it's left out because it's pseudo-ish code?

Also, why is there a pointer to a UI_Widget in UI_Comm?

Expand full comment

The Comm type is global state? In the past I’ve just used 2 bits of state per button (real or virtual), for frame-based input, one for the previous frame (on/off), and another for the current frame. Then all the combinations follow naturally. 0b00: idle, 0b01: press_started, 0b11: press_held, 0b10: press_stopped. You can do the same thing for hovering. If you need to time any input you can swap the bits for walltimes and store the last two timestamps for both on_key_down and on_key_up events. Any frame based boolean input can then be derived by just seeing if it happened within the frame interval, and double-presses and button-hold durations come for free without having to set an individual timer for any inputs, just subtract the relevant timestamps. As for names… maybe “signal”?

Expand full comment

I really like your posts, keep it up!

I have a question about the bool types - how do you decide when to use B8 and B32? What about the standard bool type?

Expand full comment