Skip to content

Instantly share code, notes, and snippets.

@viridia
Last active December 26, 2023 02:44
Show Gist options
  • Save viridia/5b4cc7c304fdb04df6c69c6c026456f5 to your computer and use it in GitHub Desktop.
Save viridia/5b4cc7c304fdb04df6c69c6c026456f5 to your computer and use it in GitHub Desktop.
Bevy UI Foundations

Bevy UI Foundational Tasks

This is a list of "prerequisite" tasks needed to bringing the Bevy UI to a level of quality suitable for production games and tools. It is not a UI framework, but rather a set of features which a UI framework can build on.

Caveat: this started out as an attempt to objectively assess each issue, but I found I couldn't resist putting in my own opinions about things.

Tasks from the Leafwing Blog Post

Round corners

Round corners are not strictly necessary, but a lot of people want them:

bevyengine/bevy#8973

Nine-Patch support

I personally don't see this as a requirement - a sufficiently capable widget templating system can handle nine-patching without any special rendering support, "nine-patch" should simply be a template that creates nine children using texture atlasing and grid layout. Not everyone agrees, however.

bevyengine/bevy#10588

Animatable trait for interpolation and blending

While this may be a valuable feature for non-UI rendering, I don't think many UI frameworks are going to use the current Bevy animation system for doing basic widget animations. If all you want is something like CSS "ease-in" between two states, there are much easier and more efficient ways to implement it.

bevyengine/bevy#4482

Winit Update

(Nothing to say here).

bevyengine/bevy#10702

Migration to Cosmic-Text

This one is huge, and will unlock many things. However, lots of work will be needed on top of this. For example, writing a text input widget that supports bidirectional text requires discontiguous selection highlights, for which we'll need to query the text layout system to determine rendering coordinates.

bevyengine/bevy#10193

World-Space UI

While this is a valuable feature, there are workarounds that work today. It should not be a blocker for an editor.

bevyengine/bevy#5476

Camera-driven UI

(Not much to say about this since I don't do XR).

bevyengine/bevy#10559

Multi-touch input

Sure.

bevyengine/bevy#15

Alternative layouts

This is more of a personal preference I think. I have no problem with flexboxes.

DioxusLabs/taffy#308 https://cuicui.nicopap.ch/layout/index.html

"Add dozens of new widgets"

I'm a bit skeptical here because of how poorly the existing "button" widget fits my needs. I'd rather see a world in which each UI framework supports an ecosystem of competing widget libraries, and users can choose between them. So for example, there are dozens of widget libraries based on React (no, we don't need that many), the same with Vue, Svelte, Solid and so on.

As a framework author, I'd rather build my own "button" (or checkbox, or radio button, etc.) than use a built-in one. The only widgets that should be built in to Bevy are ones that require serious rocket science to implement, like text editing.

Create a styling abstraction

Yes. However, I think it's important not to get too bogged down in details of serialization, and instead ask the question how we want styles to behave as objects once they are loaded. In Quill, I have carefully curated the set of CSS-like capabilities (limited selector syntax, CSS variables) so that styles can support dynamism and animation without losing performance.

Fluent support / localization

Yes, and important, but I don't see it as a blocker.

https://github.com/kgv/bevy_fluent

Generic UI navigation system

This seems like something that will require a lot of consensus building. Not a blocker.

bevyengine/rfcs#41

Pointer events and states

I don't think this is needed. A well-designed reactive framework combined with a good picking solution can do all of this without the need to build in primitive widget types that understand complex hover states. Users are going to want to build their own widgets that have their own ideas of what "hover" means (like hovering over the thumb of a slider).

We do need for the styling abstraction to be able to query which element the pointer is hovering, but that's about it.

bevyengine/bevy#7371

Cart's bsn proposal

Not going to say anything about this for now, as it would take up too much space.

bevyengine/bevy#9538

Hierarchical Bundles

Maybe. The concern here is that bundles are a "fire and forget" concept - you execute them one time, the stuff gets created, and then you're done. They don't address issues about hierarchical structures that evolve over time (that is, not just changing individual properties but changing the shape of the tree). As the "bundle" gets larger and encompasses more of the overall tree, this becomes more of a concern.

bevyengine/bevy#2565

Color interpolation

Absolutely, this should be a blocker. Not just for UI either, the current runtime polymorphism of color spaces probably impacts performance for non-UI workloads too.

bevyengine/bevy#1402

2D specific transform

Interesting, but I wouldn't consider it a blocker.

bevyengine/bevy#7876

"Blending layout strategies" for Taffy

Not sure what this means.

Add support for easing/tweening for animations

Main concern here is that inserting easing components manually in code in response to state changes is a lot of boilerplate, I'd rather this be driven by styles. That means that whatever features are supported can be represented in a succinct serializable notation or at least a terse API.

Keyboard input manager / keybindings

Good idea, main concern is that a lot of people have done these and there's a lot of diversity. Need to get consensus. Not a blocker.

https://github.com/leafwing-studios/leafwing-input-manager

Mod Picking

I've been using mod_picking a lot in Quill, haven't decided whether I will keep using it or do something different. The difficulties are not caused by mod_picking itself, but rather just the onerous nature of attaching event handlers to individual entities ("cloning storms"). An alternative strategy is to bubble events, not up the UI entity hierarchy, but rather the tree of whatever thing is generating the UI entities.

https://github.com/aevyrie/bevy_mod_picking

Relations, Relations, Relations...

Until you actually sit down and work with relations and become comfortable with them, it's hard to see how to apply them to a specific problem.

bevyengine/bevy#3742

Tasks not mentioned on the Leafwing Blog Post (or mentioned obliquely)

Better point-to-point communication for UI widgets.

A lot of UI behavior is contextual, meaning that a given widget will have different behaviors in different contexts. This is hard to model in a pure ECS framework because ECS encourages flat structures. Any context has to be encoded somehow in a global space.

Consider a popup menu: the code spawning that popup needs notification when an item is selected. Event bubbling can't work here because the popup's parent is the window, not the panel that spawned the popup. Entity-targeted events, or just events in general, require a lot of boilerplate for sending and listening to one specific event out of many. Multiple event handlers on the same entity give rise to excessive cloning of captured variables. Callbacks have issues aroud borrowing and lifetimes.

Dioxus addresses this by having its own garbage collector, which allows signals to be Copyable. However, unsure whether Dioxus's solution will work in Bevy's concurrency model.

Inline layout

Text spans should be first-class entities, mixable with "block" layout types. This is gated on the cosmic-text integration.

bevyengine/bevy#9944

Buffered rendering / compositing for 2D layouts

(Need ticket for this)

It's common in UI designs for overlay items such as dialogs, pop-up menus, toolips or other overlays (even major game modes) to "fade in", that is, to have an enter / exit transition that involves animating the opacity of the overlay. However, in order for animating opacity to look good, the opacity needs to be applied after compositing all of the child elements. This requires off-screen rendering of UIs.

Similar arguments can be made with respect to animated blurring, or other kinds of animated pixel effects - you want the effect to happen on the buffer that composites all of the child widgets.

Ideally this would be built-in to the 2D renderer such that all you would need to do is add a special Component to the UI hierarchy, telling it to render all child widgets onto the given buffer (you'd have to supply the buffer and decide how big it needs to be).

Text Input Widget

Blocked by cosmic text. This is absolutely a blocker for an editor, or even just naming saving games or characters:

bevyengine/bevy#6213

Cursors

Nice to have, should be part of styles, not a blocker:

bevyengine/bevy#9557

PositionType::Fixed

One solution to the "event bubbling from popups" problem is to allow them to be parented but still render and layout as if they were children of the window. However, this idea is ambiguous in the face of multiple windows.

bevyengine/bevy#9564

Font Families

Handling font styles is clumsy. Want to display text in bold or italics? Load a different font asset (assuming you know the asset path). We need a higher-level abstraction for fonts. This depends on cosmic-text integration.

bevyengine/bevy#9725

Transform Animation

This is the ability to scale, rotate and translate UI nodes. Currently this can be hacked around by directly modifying transform but technically we're not supposed to modify that field.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment