Feature Request: `Consumer` system runs after all `Observer`s triggered
- Dominant language
- Rust
- Stars
- 48.2k
- Forks
- 4.8k
- Avg merge
- 3d 22h
- Merged PRs (30d)
- 161
Description
## What problem does this solve or what need does it fill?
`Observer` systems can process and modify triggered events, but the execution order can not be controlled.
Except using propagating events or calling `World::trigger_ref` in exclusive systems, there is no workaround to aggregate changes in a defined order.
## What solution would you like?
A `Consumer` is a `System` with a `Post` parameter, which runs after all observers triggered for a given event type.
A `Post` contains the event processed by regular observers. It can take the event in one of the following forms:
1. the ownership of an event by value, which **breaks** usages of `World::trigger_ref`.
2. a mutable reference to an event.
3. a shared read-only reference to an event.
For 1 and 2, `Post` owns the event semantically, which means that only one `Consumer` for one event type is allowed in a world.
I implemented the solution 2 in [my fork]. Here is a minimal usage example:
```rust
let mut world = World::new();
struct MyEvent {
pub data: i32,
}
impl Event for MyEvent {
type Trigger<'a> = GlobalTrigger;
fn consumer_system() -> Option> {
fn my_event_consumer(mut event: Post) {
assert_eq!(event.data, 114514 + 1919810);
event.data /= 2;
}
Some(IntoSystem::into_system(my_event_consumer))
}
}
world.add_observer(|mut e: On| {
e.data += 114514;
});
world.add_observer(|mut e: On| {
e.data += 1919810;
});
let mut event = MyEvent { data: 0 };
world.trigger_ref(&mut event);
assert_eq!(event.data, (114514 + 1919810) / 2);
```
[my fork]: https://github.com/Fachep/bevy/commit/f86fc9fc6c6394af9e29ac9ac50da7d2238a37cd
Contributor guide
Assessment
This issue has not been assessed yet.