Skip to content

Commit

Permalink
Bubble and trouble: release notes for bubbling observers (#1823)
Browse files Browse the repository at this point in the history
Co-authored-by: Benjamin Brienen <[email protected]>
  • Loading branch information
alice-i-cecile and BenjaminBrienen authored Nov 20, 2024
1 parent cd24be0 commit f80436c
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 4 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,38 @@
<!-- Minimal Bubbling Observers -->
<!-- https://github.com/bevyengine/bevy/pull/13991 -->

<!-- TODO -->
Virtually every pointer interaction (like mouse click) is rare (humans are slow!), and often requires a complex response.
To respond to these events, `@aevyrie` created [`bevy_event_listener`],
which runs systems on-demand and bubbles unhandled events up the entity hierarchy, to their parent.

This pattern is particularly useful in UI, where unhandled interactions are often intended for the pane that *contains* the entity that's on top, but is also valuable for in-game interactions: clicking on a unit's sword should select the unit!

Rather than upstreaming `@aevyrie`'s crate as `bevy_event_hearer`, we quickly realized that there was a huge overlap with the recently added [observers].
Developed independently long after that crate's inception, observers watch for and then respond to entity-targeted events.
However, observers have no way to pass unhandled events up the hierarchy to parents who might care about them.

To support this, we've extended the [`Event`] trait with an associated type `Traversal` and an associated constant `AUTO_PROPAGATE`.
This behavior is opt-in: when you derive the `Event` type, these are set to `()` and `false` respectively.

For the [`Pointer<E>`] event type, we've chosen to implement this as:

```rust
impl <E> Event for Pointer<E>{
type Traversal = &Parent;
const AUTO_PROPAGATE: bool = true;
}
```

This means that, unless you call [`Trigger::propagate(false)`], pointer events will be replicated up the hierarchy (accessing the `Entity` stored in the [`Parent`] component) until it reaches the entity root.

Any type that implements the [`Traversal`] trait can be used as the associated type and can access arbitrary read-only query data from the world.
While using the standard entity hierarchy is a sensible choice for *many* applications, bubbling can be used for arbitrary event propagation using your own [proto-relations].
Let us know what you cook up: user feedback is indispensable for building a better Bevy!

[Observers]: https://bevyengine.org/news/bevy-0-14/#ecs-hooks-and-observers
[`bevy_event_listener`]: (https://github.com/aevyrie/bevy_eventlistener)
[`Event`]: https://docs.rs/bevy/0.15.0/bevy/ecs/event/trait.Event.html
[`Pointer<E>`]: https://docs.rs/bevy/0.15.0/bevy/picking/events/struct.Pointer.html
[`Trigger::propagate(false)`]: https://docs.rs/bevy/0.15.0/bevy/ecs/prelude/struct.Trigger.html#method.propagate
[`Parent`]: https://docs.rs/bevy/0.15.0/bevy/hierarchy/struct.Parent.html
[proto-relations]: https://github.com/bevyengine/bevy/issues/3742
12 changes: 9 additions & 3 deletions release-content/0.15/release-notes/_release-notes.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,16 @@ prs = [14269]
file_name = "14269_Basic_isometry_types.md"

[[release_notes]]
title = "Minimal Bubbling Observers"
contributors = [
"@aevyrie",
"@cart",
"@alice-i-cecile",
"@torsteingrindvik",
"@BenjaminBrienen",
]
title = "Bubbling Observers"
authors = ["@NthTensor"]
contributors = ["@cart", "@alice-i-cecile", "@torsteingrindvik"]
prs = [13991]
prs = [13991, 15385]
file_name = "13991_Minimal_Bubbling_Observers.md"

[[release_notes]]
Expand Down

0 comments on commit f80436c

Please sign in to comment.