# When Bevy Was Five by Talin ## A Bit About Me Although I have been programming professionally for almost 50 years, I don't have a degree - in fact, I have never taken a computer science class. Instead, I [learned programming in the US Air Force](https://dreamertalin.medium.com/usaf-1976-1980-4e2e9e4ab7f9) back in 1976. That, plus I was fortunate enough to gain access to back issues of *Byte*, *Kilobaud*, *Creative Computing*, *Dr. Dobbs*, and other magazines. I published my first commercial game, [Guardian](https://www.youtube.com/watch?v=ItddIniQh_k), in 1982 for the Radio Shack Color Computer. A few years after that, I had a brief few years of fame for my Commodore Amiga game, [The Faery Tale Adventure](https://dreamertalin.medium.com/the-faery-tale-adventure-a-personal-history-4fae0617a18d), published in 1986. In 1991, I co-founded a game company, [The Dreamers Guild](https://en.wikipedia.org/wiki/The_Dreamers_Guild), which grew to over 80 employees before it went bankrupt. Later, [I worked for a while at Maxis](https://dreamertalin.medium.com/maxis-and-ea-2002-2007-c07f50f66314) on *The Sims 2* and *Sim City 4*. However, I didn't much care for the corporate culture at Electronic Arts, and decided to leave the games industry in 2007. After spending a decade working at big tech companies like Google and AWS, I retired in 2021, and since then have spent most of my time doing hobby game development. I started writing a game engine in TypeScript using three.js, but in 2023 I switched over to Rust and Bevy. ## Why Bevy? I'd previously written games and game tools in many different programming languages, including BASIC (the first game I ever wrote was on an [ASR-33 teletype](https://en.wikipedia.org/wiki/Teletype_Model_33)), C (both K&R and ANSI variants), C++, C#, Java, Python, and TypeScript. When I started my new project in 2021, I had to decide what language to use. After having done C++ development for over 15 years, I was tired of it, and I knew that I didn't want to go back there. I wanted to program in a modern language, with powerful static typing and type inference. I had really enjoyed working in TypeScript, but I yearned for something that would provide native code performance. I investigated a number of alternatives (Go and Swift for example), both of which had significant downsides in my opinion. Rust was the clear winner for me, although it took me a long time to really become fluent in it. Unfortunately, the state of game engines in Rust was very immature in 2021. I had spent a few weeks working with [Amethyst](https://github.com/amethyst/amethyst), but I could tell that it was "not there yet". I saw the initial release announcement for Bevy on Reddit, but I didn't pay too much attention at the time - it seemed like just another one of the several dozen fly-by-night game engine crates available for Rust. Most of these never went anywhere. However, Bevy kept popping up on my radar. The Bevy team kept releasing new versions on a regular basis. Then I started looking more closely at the releases: 50 contributors, 100 contributors! That's a lot of people! (It's now up to 270.) OK, *this is starting to be worth my attention*. As someone who had previously worked as a senior software engineer, I am all about "due diligence": when you work for a large company, and you need a library to solve a problem, you don't just pick the first open-source package that comes up on the search page for PyPI or npmjs.com. Even if the README.md seems like it fits the bill, you need to look deeper. Does it have an active development community, and a robust release process? If you report a bug, is it likely to get fixed in a timely fashion? Are the maintainers *serious people*? The more I looked at Bevy, the more I realized that it ticked all of my boxes. So in 2023, I decided to switch. ## "Are We Editor Yet?" I've written many game editors: even as far back as 1985, I was writing music and animation editors for my Amiga games. Creating tools for creative people is something I've always enjoyed, perhaps even more so than actually writing games. At this point, I can imagine readers asking "if writing editors is so much fun, why isn't the Bevy editor done yet?" The answer is that Bevy hasn't previously had the foundations needed to build an editor. But we're getting close! As one example, Bevy's UI crate, `bevy_ui`, is technically capable of building an editor UI today - but it's too onerous to use for anything but the simplest UIs. To explain this in more detail, I'd like to offer an analogy. Suppose you were tasked with writing a web page for a commercial site such as amazon.com or the New York Times. Only, for some reason you weren't allowed to use HTML or CSS. Instead, you had to write it all in JavaScript. Each headline, paragraph, image, and hyperlink -- each *italicized word* had to be inserted using a function call. Could you make a web page this way? Yes, you could! It's *technically* possible - but you'd be *insane* to do it! It would be waaaaay too much work, and the result would be totally unmaintainable. This is the situation that `bevy_ui` is in today. Does this mean that `bevy_ui` is bad, and we need to start over with something else? No! Bevy UI is a *low-level* API, which can be used as the basis for higher-level APIs. Consider our web page analogy: inserting hyperlinks using individual function calls is tedious, sure - but under the hood, that's exactly what the browser does! When the browser interprets HTML, it builds up the DOM ("Document Object Model") node by node, just as our hypothetical API would. So what we need is to build that higher-level API - or rather, multiple high-level APIs -- a whole "stack". The good news is that we've recently made significant progress on this. ## Headless Widgets Up to this point, what we have had in `bevy_ui` is basically a DOM. The next step up from that is "widgets" - self-contained bundles of interactive behavior that can be instantiated and customized. In the React world, there are dozens of different widget libraries, such as [Material UI](https://mui.com/), [Chakra](https://www.chakra-ui.com/), or [HeroUI](https://www.heroui.com/). In a previous project, I personally evaluated two dozen different UI frameworks (back to that "due diligence" thing again). However, these widget libraries are *highly opinionated* - meaning that each one implements a particular art style. While that might be fine for something like an editor, games need more flexibility: games thrive on novelty, and game creators need the ability to make their UI fit within the visual theme of their game, whether that be futuristic, medieval, or cartoony. For example, the game I am working on incorporates an Art Nouveau style, inspired by the work of [Alphonse Mucha](https://i0.wp.com/www.proantic.com/magazine/wp-content/uploads/2018/10/azz.jpg): ![chest-loot-cropped](https://hackmd.io/_uploads/ryWc06gclx.png) (Note: I created this image using [Inkscape](https://inkscape.org/).) In recent years, the web development world has seen the rist of "headless" widget libraries such as [headlessui](https://headlessui.com/) and [reakit](https://reakit.io/). These libraries provide the complex behaviors for buttons, checkboxes, sliders, menus and other widgets, but without any inherent styling. Instead, it's up to the user to customize the widget appearance using stylesheets. (This brings me back to how, when I was growing up, my Dad used to shop at a store that sold "unfinished furniture" - that is, chairs and tables which were bare wood. The customer would then take the item home and either paint or stain them as desired.) Can we not do something similar in Bevy? It turns out that we can, with a little bit of ingenuity. Because Bevy is an ECS framework, we need to take an ECS-centric approach to the problem. These "headless" widgets are ECS components, and they use Bevy's observers and picking subsystems to provide all of the subtle and complex behaviors of widgets. Rather than using a stylesheet language like CSS, we need to apply styles by watching for changes on the components that represent the widgets state: this includes properties like `hovered`, `disabled`, `pressed`, `checked` and so on, as well as numeric quantities like slider values. This can be done using ECS systems, observers, or some future reactive solution. Then, it's just a matter of including these special components with your widget bundle. Bevy 0.17 will ship with an initial collection of "simple" headless widgets (button, checkbox, slider, toggle switch, and so on.) More complex widgets such as dropdown menus have been prototyped, but aren't quite ready to be released just yet. ## Accessibility One key feature of the new Bevy widgets is support for accesibility, such as integration with screen readers and other assistive technologies. When I first started working as a web developer, I was vaguely aware of the need for accessibility support and of standards like [ARIA](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) (Accessible Rich Internet Applications), but I didn't think too much of it at the time. Like most software engineers, accessibility (like localization and security) was very much a "back burner" concern - something we'll get around to eventually (maybe). After all, while a developer might get a bonus for meeting a feature deadline, no one ever got promoted (or closed another round of VC funding) for making the app accessible, right? That was until I met Nicole Torcelli. I had recently joined the Google+ team, and Nicole worked in the same building. She's the kind of person that it would be easy to underestimate, walking the corridors with her white cane and crooked posture - but doing so would be a grave mistake. As I started working with her - watching her rapidly type on the keyboard while the speech synthesizer babbled away at high speed - I realized that not only could blind people use computers, but that they could write code! With proper indentation even! Nicole and I joined forces to create a new widget library, named, "quantum wiz" for use in Google+, which would have accessibility "built into it's DNA". Instead of trying to exhort developers to be good citizens and include all the right ARIA tags in their HTML, users of our widgets would get these behaviors for free. Although [Google+ itself was a failure](https://onezero.medium.com/why-google-failed-4b9db05b973b), the widgets I created were eventually used in Google Sheets and Google Accounts. In 2015, when I left Google, I was presented with the following "trophy" by the accessibility team for my contributions: ![service-dog-plushie](https://hackmd.io/_uploads/rk4Td0eqle.jpg) (The image is a stuffed animal toy of a service dog.) Bevy finds itself in a very similar situation today: we have support for accessibility via `accesskit`, but it doesn't do much good unless developers actually invoke the API. And most developers don't know much about accessibility technologies, or put much importance on them. A surprising number of developers are unaware of the fact that modern operating systems have screen readers built in, which can be enabled in the OS settings panel. ("How do I test this?" is a common question.) So part of the design goal of the new headless widgets is to support accessibility "by default". Even better: there's a strong overlap between "accessibility features" and "power user features" - such as being able to drive the UI via keyboard shortcuts. ## Bevy Feathers The headless widgets are an important step, but by themselves are not enough: for someone building an editor, they don't want to spend typing mucking around with styles and colors. They want an out-of-the box widget solution that they can just plug in and go. Fortunately, diligent and industrious Bevy contributors have already spent a great deal of effort settling on a consistent visual style for the Bevy editor, as can be seen [here](https://rinoxide.substack.com/p/bevys-fifth-birthday-the-editor). So we know, pretty much, what the editor's visual style is going to look like. At the same time, however, I don't merely want to build the "official" Bevy editor. I'm personally most interested in building custom editors for specific tasks, like surface designers, low-poly tree generators, animation graph editors, and so on. And I'm [not the only person that feels this way](https://www.charlotte.fyi/posts/towards-multiple-editors). The good news is, there's no reason why all these editors can't share the same opinionated widget set. ![image](https://hackmd.io/_uploads/By16e1Zcge.png) When I started working on this project, there was only one design requirement which I insisted was non-negotiable: that the new widget set have a "brand name" that was playful and creative, and not something boring like "The Bevy Editor Widgets". There are several reasons for this: * The brand name was meant to represent not just the widgets themselves, but the name of the visual style which the widgets embodied. * During my work on past projects like GMail and Google+, I learned that UX designers often use code names for different iterations of the visual style. For example, before Google+ launched, there were nine different iterations of the app's visual style, with names such as "Red Shift" and "Inception". * My hope is that eventually, there will be an ecosystem of multiple competing widget libaries, each with their own distinctive style. This will require that these styles have names. * It's generally assumed that every game's UI will be unique and distinct from every other game, but I don't see why this should be true, particularly in the indie gamedev world. I have an idea for a "standard cartoon" UI which would be much more playful and less professional-looking (much more rounded), which would also lean much more heavily into animation - like having buttons that "inflate" when hovered. After soliciting suggestions on the Bevy Discord, we eventually settled on "Feathers" as being an appropriately playful, bird-themed brand name. Feathers will ship in 0.17, however it is currently marked as "experimental" and hidden behind a feature flag. The main reason for this is that Feathers is intended to be a "BSN-first" widget library, and since BSN hasn't shipped yet, it's a certainty that the APIs for Feathers are going to change significantly. ## Next: BSN Although [BSN](https://github.com/bevyengine/bevy/pull/20158) (Bevy Scene Notation [yes, cart, I know you want it to stand for "Bevy SceNe", but I'm afraid that ship has sailed]) isn't going to be included for 0.17, early access implementations are already available via git. The feathers widgets have been migrated to the new templating system, and work very well in that context. I can say from experience that it's a significant quality-of-life improvement. ## Next-Next: World Inspector Improvements in `bevy_ui` are going to be critical to the develoment of the Bevy Scene Editor, but this is not the only critical piece currently missing. Just dealing with scene serialization is going to be a huge task, as well as other foundational capabilities such as file browsing, undo / redo, and user preferences. Fortunately, we don't have to wait for the full editor to be finished before we can take advantage of the new UI tools. One of the projects currently in development is a native "World Inspector" plugin. Bevy already has an Egui-based inspector crate, but users have long wanted a Bevy-native solution. The world inspector should be able to use many of the same underlying components as the scene editor, and serve as a kind of "dress rehearsal" for building the full editor app. ## After That: Reactivity Although the combination of BSN and standardized widgets improves the developer experience of `bevy_ui` significantly, it is still a long way from *ideal*. While BSN helps with defining the hierarchical structure of the UI in a declarative way, it doesn't really address the problem of wiring up the *behavior* of the various components. Building a complex interactive logic requires a bunch of moving parts: observers, systems, and lots of marker components. An alternative approach - one that many people have lobbied for - would be some kind of reactive solution, similar to what is seen in [React.js](https://react.dev/) (although what we currently envision is actually closer to [Solid.js](https://www.solidjs.com/) or [Svelte](https://svelte.dev/)). A reactive solution will allow the visual definitions and the widget logic to be *co-located*, which is an important organizing principle for modern UIs. Unlike the earlier "separation of layers" architecture favored in the jQuery era, most developers today prefer a style of organization in which UI components are integrated, modular units: all the code for the login dialog is grouped together in one place, all the code for the inventory panel is grouped together in another, and so on with the settings dialog, HUD, and the rest. Parent elements are responsible for orchestrating the interactions between their children, but the logical connections between elements need not be strictly hierarchical: pressing the "logout" button in the sidebar can affect the state of the user's account name shown in the page header, despite the fact that these are separate components. However, implementing a reactive framework for Bevy is by no means straightforward. There are really three separate problems that need to be solved: * The **data dependency** problem: how can we define functions that automatically run in response to changes to multiple data sources of different types? * The **signals** problem: how can we package up these data dependent functions so that they can be passed around between subsystems? * The **incrementalization** problem: how to efficiently update an entity hierarchy in a way that preserves the parts that aren't changing? Most existing reactivity solutions tend to fall into one of two camps: The *coarse-grained* solutions, like React.js, associate reactions with template instances, which are relatively large chunks containing multiple elements. These solutions rely heavily on "diffing" to be able to efficiently and incrementally update the display. The *fine-grained* camp, exemplified by Solid.js, uses many smaller "micro-reactions" that are associated with individual entities, or even smaller: individual properties of those entities. These generally have no need of diffing because the changes they make are already minimal. This idea can be adapted to Bevy by making each reaction a component. (In theory, both approaches use diffing, it's just that they use it in a different place. Fine-grained approaches often rely on memoization, which is a kind of "diff" that happens upstream). There are already a number of third-party crates, such as [Cobweb](https://github.com/UkoeHB/bevy_cobweb) and [Jonmo](https://github.com/databasedav/jonmo), which implement reactivity effectively. However, as these are third-party crates, they are not able to benefit from deep integration into Bevy's World model. A key challenge here is that Bevy's current change detection system is not a great fit for doing efficient reactivity: it either notifies you too little, too much, or at the wrong time. If I have a widget, or a computed value, which depends on five inputs, what I want to know is whether any of those five inputs actually changed, so that I can recompute the thing - I don't need to recalculate it five times if all five inputs changed at once. There's also no unified paradigm for watching changes across components, resources, assets and queries - instead each of these has its own change detection methods. So if I have a function that depends on inputs from, say, a query and an asset, I need to invent an ad-hoc solution. Some of the third-party reactive solutions get around this by estanblishing their own reactive-friendly data types, but ideally we would want something that works with ordinary Bevy data structures. This design constraint is predicated on the assumption that maximizing performance is paramount: after all, most reactive frameworks are carefully designed to recompute output values as little as possible. If we relax the performance constraint somewhat, then there are simpler approaches. One is to simply poll the inputs every frame; another is to poll, but then memoize the result, only taking action when the memo changes. My hope is that BSN will unlock a wave of experimentation by Bevy developers, and we'll be able to build consensus around a common approach. --- <img style="float: left;" src="https://hackmd.io/_uploads/SkVrOl-cee.png" />