bevy/crates/bevy_ecs/src/event/send_event.rs
SpecificProtagonist b2d3371814
Event source location tracking (#16778)
# Objective

Fixes #16776

## Solution

- reflect `&'static Location` as an opaque type
- I've added this to `impls/std.rs` because other core types are there
too. Maybe they should be split out into a `core.rs` in another PR.
- add source location to `EventId` (behind the
`tracking_change_detection` feature flag)

## Testing

---

## Showcase
```rust
fn apply_damage_to_health(
    mut dmg_events: EventReader<DealDamage>,
) {
    for (event, event_id) in dmg_events.read_with_id() {
        info!(
            "Applying {} damage, triggered by {}",
            event.amount, event_id.caller
        );
…
```
```
2024-12-12T01:21:50.126827Z  INFO event: Applying 9 damage, triggered by examples/ecs/event.rs:47:16
```

## Migration Guide

- If you manually construct a `SendEvent`, use `SendEvent::new()`

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-12-12 18:12:53 +00:00

38 lines
1.1 KiB
Rust

#[cfg(feature = "track_change_detection")]
use core::panic::Location;
use super::{Event, Events};
use crate::world::{Command, World};
/// A command to send an arbitrary [`Event`], used by [`Commands::send_event`](crate::system::Commands::send_event).
pub struct SendEvent<E: Event> {
/// The event to send.
pub event: E,
/// The source code location that triggered this command.
#[cfg(feature = "track_change_detection")]
pub caller: &'static Location<'static>,
}
// This does not use `From`, as the resulting `Into` is not track_caller
impl<E: Event> SendEvent<E> {
/// Constructs a new `SendEvent` tracking the caller.
pub fn new(event: E) -> Self {
Self {
event,
#[cfg(feature = "track_change_detection")]
caller: Location::caller(),
}
}
}
impl<E: Event> Command for SendEvent<E> {
fn apply(self, world: &mut World) {
let mut events = world.resource_mut::<Events<E>>();
events.send_with_caller(
self.event,
#[cfg(feature = "track_change_detection")]
self.caller,
);
}
}