bevy/benches/Cargo.toml
Miles Silberling-Cook ed2b8e0f35
Minimal Bubbling Observers (#13991)
# Objective

Add basic bubbling to observers, modeled off `bevy_eventlistener`.

## Solution

- Introduce a new `Traversal` trait for components which point to other
entities.
- Provide a default `TraverseNone: Traversal` component which cannot be
constructed.
- Implement `Traversal` for `Parent`.
- The `Event` trait now has an associated `Traversal` which defaults to
`TraverseNone`.
- Added a field `bubbling: &mut bool` to `Trigger` which can be used to
instruct the runner to bubble the event to the entity specified by the
event's traversal type.
- Added an associated constant `SHOULD_BUBBLE` to `Event` which
configures the default bubbling state.
- Added logic to wire this all up correctly.

Introducing the new associated information directly on `Event` (instead
of a new `BubblingEvent` trait) lets us dispatch both bubbling and
non-bubbling events through the same api.

## Testing

I have added several unit tests to cover the common bugs I identified
during development. Running the unit tests should be enough to validate
correctness. The changes effect unsafe portions of the code, but should
not change any of the safety assertions.

## Changelog

Observers can now bubble up the entity hierarchy! To create a bubbling
event, change your `Derive(Event)` to something like the following:

```rust
#[derive(Component)]
struct MyEvent;

impl Event for MyEvent {
    type Traverse = Parent; // This event will propagate up from child to parent.
    const AUTO_PROPAGATE: bool = true; // This event will propagate by default.
}
```

You can dispatch a bubbling event using the normal
`world.trigger_targets(MyEvent, entity)`.

Halting an event mid-bubble can be done using
`trigger.propagate(false)`. Events with `AUTO_PROPAGATE = false` will
not propagate by default, but you can enable it using
`trigger.propagate(true)`.

If there are multiple observers attached to a target, they will all be
triggered by bubbling. They all share a bubbling state, which can be
accessed mutably using `trigger.propagation_mut()` (`trigger.propagate`
is just sugar for this).

You can choose to implement `Traversal` for your own types, if you want
to bubble along a different structure than provided by `bevy_hierarchy`.
Implementers must be careful never to produce loops, because this will
cause bevy to hang.

## Migration Guide
+ Manual implementations of `Event` should add associated type `Traverse
= TraverseNone` and associated constant `AUTO_PROPAGATE = false`;
+ `Trigger::new` has new field `propagation: &mut Propagation` which
provides the bubbling state.
+ `ObserverRunner` now takes the same `&mut Propagation` as a final
parameter.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Torstein Grindvik <52322338+torsteingrindvik@users.noreply.github.com>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2024-07-15 13:39:41 +00:00

75 lines
1.6 KiB
TOML

[package]
name = "benches"
edition = "2021"
description = "Benchmarks that test Bevy's performance"
publish = false
license = "MIT OR Apache-2.0"
[dev-dependencies]
glam = "0.27"
rand = "0.8"
rand_chacha = "0.3"
criterion = { version = "0.3", features = ["html_reports"] }
bevy_app = { path = "../crates/bevy_app" }
bevy_ecs = { path = "../crates/bevy_ecs", features = ["multi_threaded"] }
bevy_hierarchy = { path = "../crates/bevy_hierarchy" }
bevy_internal = { path = "../crates/bevy_internal" }
bevy_math = { path = "../crates/bevy_math" }
bevy_reflect = { path = "../crates/bevy_reflect" }
bevy_render = { path = "../crates/bevy_render" }
bevy_tasks = { path = "../crates/bevy_tasks" }
bevy_utils = { path = "../crates/bevy_utils" }
[profile.release]
opt-level = 3
lto = true
[[bench]]
name = "change_detection"
path = "benches/bevy_ecs/change_detection.rs"
harness = false
[[bench]]
name = "ecs"
path = "benches/bevy_ecs/benches.rs"
harness = false
[[bench]]
name = "reflect_list"
path = "benches/bevy_reflect/list.rs"
harness = false
[[bench]]
name = "reflect_map"
path = "benches/bevy_reflect/map.rs"
harness = false
[[bench]]
name = "reflect_struct"
path = "benches/bevy_reflect/struct.rs"
harness = false
[[bench]]
name = "parse_reflect_path"
path = "benches/bevy_reflect/path.rs"
harness = false
[[bench]]
name = "iter"
path = "benches/bevy_tasks/iter.rs"
harness = false
[[bench]]
name = "bezier"
path = "benches/bevy_math/bezier.rs"
harness = false
[[bench]]
name = "torus"
path = "benches/bevy_render/torus.rs"
harness = false
[[bench]]
name = "entity_hash"
path = "benches/bevy_ecs/world/entity_hash.rs"
harness = false