From 219b5930f1435d46da65df0344fe6dcf2a0dc92e Mon Sep 17 00:00:00 2001 From: Christian Hughes <9044780+ItsDoot@users.noreply.github.com> Date: Wed, 9 Oct 2024 08:39:29 -0700 Subject: [PATCH] Rename `App/World::observe` to `add_observer`, `EntityWorldMut::observe_entity` to `observe`. (#15754) # Objective - Closes #15752 Calling the functions `App::observe` and `World::observe` doesn't make sense because you're not "observing" the `App` or `World`, you're adding an observer that listens for an event that occurs *within* the `World`. We should rename them to better fit this. ## Solution Renames: - `App::observe` -> `App::add_observer` - `World::observe` -> `World::add_observer` - `Commands::observe` -> `Commands::add_observer` - `EntityWorldMut::observe_entity` -> `EntityWorldMut::observe` (Note this isn't a breaking change as the original rename was introduced earlier this cycle.) ## Testing Reusing current tests. --- .../benches/bevy_ecs/observers/propagation.rs | 6 +- benches/benches/bevy_ecs/observers/simple.rs | 4 +- crates/bevy_app/src/app.rs | 6 +- .../bevy_dev_tools/src/ci_testing/systems.rs | 2 +- crates/bevy_ecs/README.md | 4 +- crates/bevy_ecs/src/observer/mod.rs | 181 ++++++++++++------ crates/bevy_ecs/src/observer/runner.rs | 20 +- crates/bevy_ecs/src/system/commands/mod.rs | 11 +- crates/bevy_ecs/src/system/observer_system.rs | 4 +- crates/bevy_ecs/src/world/entity_ref.rs | 2 +- crates/bevy_pbr/src/lib.rs | 6 +- crates/bevy_picking/src/events.rs | 2 +- crates/bevy_picking/src/lib.rs | 2 +- crates/bevy_render/src/sync_world.rs | 8 +- crates/bevy_scene/src/scene_spawner.rs | 2 +- crates/bevy_winit/src/cursor.rs | 2 +- examples/animation/animated_fox.rs | 2 +- examples/ecs/observer_propagation.rs | 2 +- examples/ecs/observers.rs | 6 +- examples/ecs/removal_detection.rs | 2 +- 20 files changed, 168 insertions(+), 106 deletions(-) diff --git a/benches/benches/bevy_ecs/observers/propagation.rs b/benches/benches/bevy_ecs/observers/propagation.rs index 75fb1f9347e8f..acd07aac566e7 100644 --- a/benches/benches/bevy_ecs/observers/propagation.rs +++ b/benches/benches/bevy_ecs/observers/propagation.rs @@ -106,15 +106,15 @@ fn add_listeners_to_hierarchy( world: &mut World, ) { for e in roots.iter() { - world.entity_mut(*e).observe_entity(empty_listener::); + world.entity_mut(*e).observe(empty_listener::); } for e in leaves.iter() { - world.entity_mut(*e).observe_entity(empty_listener::); + world.entity_mut(*e).observe(empty_listener::); } let mut rng = deterministic_rand(); for e in nodes.iter() { if rng.gen_bool(DENSITY as f64 / 100.0) { - world.entity_mut(*e).observe_entity(empty_listener::); + world.entity_mut(*e).observe(empty_listener::); } } } diff --git a/benches/benches/bevy_ecs/observers/simple.rs b/benches/benches/bevy_ecs/observers/simple.rs index 7b7acc5564a55..bc42710cf96c3 100644 --- a/benches/benches/bevy_ecs/observers/simple.rs +++ b/benches/benches/bevy_ecs/observers/simple.rs @@ -17,7 +17,7 @@ pub fn observe_simple(criterion: &mut Criterion) { group.bench_function("trigger_simple", |bencher| { let mut world = World::new(); - world.observe(empty_listener_base); + world.add_observer(empty_listener_base); bencher.iter(|| { for _ in 0..10000 { world.trigger(EventBase) @@ -29,7 +29,7 @@ pub fn observe_simple(criterion: &mut Criterion) { let mut world = World::new(); let mut entities = vec![]; for _ in 0..10000 { - entities.push(world.spawn_empty().observe_entity(empty_listener_base).id()); + entities.push(world.spawn_empty().observe(empty_listener_base).id()); } entities.shuffle(&mut deterministic_rand()); bencher.iter(|| { diff --git a/crates/bevy_app/src/app.rs b/crates/bevy_app/src/app.rs index e9852d90f1457..7050c61d5888a 100644 --- a/crates/bevy_app/src/app.rs +++ b/crates/bevy_app/src/app.rs @@ -1267,7 +1267,7 @@ impl App { /// # struct Friend; /// # /// // An observer system can be any system where the first parameter is a trigger - /// app.observe(|trigger: Trigger, friends: Query>, mut commands: Commands| { + /// app.add_observer(|trigger: Trigger, friends: Query>, mut commands: Commands| { /// if trigger.event().friends_allowed { /// for friend in friends.iter() { /// commands.trigger_targets(Invite, friend); @@ -1275,11 +1275,11 @@ impl App { /// } /// }); /// ``` - pub fn observe( + pub fn add_observer( &mut self, observer: impl IntoObserverSystem, ) -> &mut Self { - self.world_mut().observe(observer); + self.world_mut().add_observer(observer); self } } diff --git a/crates/bevy_dev_tools/src/ci_testing/systems.rs b/crates/bevy_dev_tools/src/ci_testing/systems.rs index c3d83ec01ff04..20c758a91cdfc 100644 --- a/crates/bevy_dev_tools/src/ci_testing/systems.rs +++ b/crates/bevy_dev_tools/src/ci_testing/systems.rs @@ -25,7 +25,7 @@ pub(crate) fn send_events(world: &mut World, mut current_frame: Local) { let path = format!("./screenshot-{}.png", *current_frame); world .spawn(Screenshot::primary_window()) - .observe_entity(save_to_disk(path)); + .observe(save_to_disk(path)); info!("Took a screenshot at frame {}.", *current_frame); } // Custom events are forwarded to the world. diff --git a/crates/bevy_ecs/README.md b/crates/bevy_ecs/README.md index a85fc07900a7b..a8a396ef96185 100644 --- a/crates/bevy_ecs/README.md +++ b/crates/bevy_ecs/README.md @@ -315,7 +315,7 @@ struct MyEvent { let mut world = World::new(); -world.observe(|trigger: Trigger| { +world.add_observer(|trigger: Trigger| { println!("{}", trigger.event().message); }); @@ -339,7 +339,7 @@ struct Explode; let mut world = World::new(); let entity = world.spawn_empty().id(); -world.observe(|trigger: Trigger, mut commands: Commands| { +world.add_observer(|trigger: Trigger, mut commands: Commands| { println!("Entity {:?} goes BOOM!", trigger.entity()); commands.entity(trigger.entity()).despawn(); }); diff --git a/crates/bevy_ecs/src/observer/mod.rs b/crates/bevy_ecs/src/observer/mod.rs index 5dcc7f70b65cb..5e87a9d01ce60 100644 --- a/crates/bevy_ecs/src/observer/mod.rs +++ b/crates/bevy_ecs/src/observer/mod.rs @@ -364,8 +364,29 @@ impl Observers { } impl World { - /// Spawns a "global" [`Observer`] and returns its [`Entity`]. - pub fn observe( + /// Spawns a "global" [`Observer`] which will watch for the given event. + /// Returns its [`Entity`] as a [`EntityWorldMut`]. + /// + /// **Calling [`observe`](EntityWorldMut::observe) on the returned + /// [`EntityWorldMut`] will observe the observer itself, which you very + /// likely do not want.** + /// + /// # Example + /// + /// ``` + /// # use bevy_ecs::prelude::*; + /// #[derive(Component)] + /// struct A; + /// + /// # let mut world = World::new(); + /// world.add_observer(|_: Trigger| { + /// // ... + /// }); + /// world.add_observer(|_: Trigger| { + /// // ... + /// }); + /// ``` + pub fn add_observer( &mut self, system: impl IntoObserverSystem, ) -> EntityWorldMut { @@ -593,10 +614,14 @@ mod tests { let mut world = World::new(); world.init_resource::(); - world.observe(|_: Trigger, mut res: ResMut| res.observed("add")); - world.observe(|_: Trigger, mut res: ResMut| res.observed("insert")); - world.observe(|_: Trigger, mut res: ResMut| res.observed("replace")); - world.observe(|_: Trigger, mut res: ResMut| res.observed("remove")); + world.add_observer(|_: Trigger, mut res: ResMut| res.observed("add")); + world + .add_observer(|_: Trigger, mut res: ResMut| res.observed("insert")); + world.add_observer(|_: Trigger, mut res: ResMut| { + res.observed("replace"); + }); + world + .add_observer(|_: Trigger, mut res: ResMut| res.observed("remove")); let entity = world.spawn(A).id(); world.despawn(entity); @@ -611,10 +636,14 @@ mod tests { let mut world = World::new(); world.init_resource::(); - world.observe(|_: Trigger, mut res: ResMut| res.observed("add")); - world.observe(|_: Trigger, mut res: ResMut| res.observed("insert")); - world.observe(|_: Trigger, mut res: ResMut| res.observed("replace")); - world.observe(|_: Trigger, mut res: ResMut| res.observed("remove")); + world.add_observer(|_: Trigger, mut res: ResMut| res.observed("add")); + world + .add_observer(|_: Trigger, mut res: ResMut| res.observed("insert")); + world.add_observer(|_: Trigger, mut res: ResMut| { + res.observed("replace"); + }); + world + .add_observer(|_: Trigger, mut res: ResMut| res.observed("remove")); let mut entity = world.spawn_empty(); entity.insert(A); @@ -631,10 +660,14 @@ mod tests { let mut world = World::new(); world.init_resource::(); - world.observe(|_: Trigger, mut res: ResMut| res.observed("add")); - world.observe(|_: Trigger, mut res: ResMut| res.observed("insert")); - world.observe(|_: Trigger, mut res: ResMut| res.observed("replace")); - world.observe(|_: Trigger, mut res: ResMut| res.observed("remove")); + world.add_observer(|_: Trigger, mut res: ResMut| res.observed("add")); + world + .add_observer(|_: Trigger, mut res: ResMut| res.observed("insert")); + world.add_observer(|_: Trigger, mut res: ResMut| { + res.observed("replace"); + }); + world + .add_observer(|_: Trigger, mut res: ResMut| res.observed("remove")); let mut entity = world.spawn_empty(); entity.insert(S); @@ -653,10 +686,14 @@ mod tests { let entity = world.spawn(A).id(); - world.observe(|_: Trigger, mut res: ResMut| res.observed("add")); - world.observe(|_: Trigger, mut res: ResMut| res.observed("insert")); - world.observe(|_: Trigger, mut res: ResMut| res.observed("replace")); - world.observe(|_: Trigger, mut res: ResMut| res.observed("remove")); + world.add_observer(|_: Trigger, mut res: ResMut| res.observed("add")); + world + .add_observer(|_: Trigger, mut res: ResMut| res.observed("insert")); + world.add_observer(|_: Trigger, mut res: ResMut| { + res.observed("replace"); + }); + world + .add_observer(|_: Trigger, mut res: ResMut| res.observed("remove")); // TODO: ideally this flush is not necessary, but right now observe() returns WorldEntityMut // and therefore does not automatically flush. @@ -672,26 +709,26 @@ mod tests { fn observer_order_recursive() { let mut world = World::new(); world.init_resource::(); - world.observe( + world.add_observer( |obs: Trigger, mut res: ResMut, mut commands: Commands| { res.observed("add_a"); commands.entity(obs.entity()).insert(B); }, ); - world.observe( + world.add_observer( |obs: Trigger, mut res: ResMut, mut commands: Commands| { res.observed("remove_a"); commands.entity(obs.entity()).remove::(); }, ); - world.observe( + world.add_observer( |obs: Trigger, mut res: ResMut, mut commands: Commands| { res.observed("add_b"); commands.entity(obs.entity()).remove::(); }, ); - world.observe(|_: Trigger, mut res: ResMut| { + world.add_observer(|_: Trigger, mut res: ResMut| { res.observed("remove_b"); }); @@ -709,11 +746,11 @@ mod tests { fn observer_trigger_ref() { let mut world = World::new(); - world.observe(|mut trigger: Trigger| trigger.event_mut().counter += 1); - world.observe(|mut trigger: Trigger| trigger.event_mut().counter += 2); - world.observe(|mut trigger: Trigger| trigger.event_mut().counter += 4); + world.add_observer(|mut trigger: Trigger| trigger.event_mut().counter += 1); + world.add_observer(|mut trigger: Trigger| trigger.event_mut().counter += 2); + world.add_observer(|mut trigger: Trigger| trigger.event_mut().counter += 4); // This flush is required for the last observer to be called when triggering the event, - // due to `World::observe` returning `WorldEntityMut`. + // due to `World::add_observer` returning `WorldEntityMut`. world.flush(); let mut event = EventWithData { counter: 0 }; @@ -725,11 +762,17 @@ mod tests { fn observer_trigger_targets_ref() { let mut world = World::new(); - world.observe(|mut trigger: Trigger| trigger.event_mut().counter += 1); - world.observe(|mut trigger: Trigger| trigger.event_mut().counter += 2); - world.observe(|mut trigger: Trigger| trigger.event_mut().counter += 4); + world.add_observer(|mut trigger: Trigger| { + trigger.event_mut().counter += 1; + }); + world.add_observer(|mut trigger: Trigger| { + trigger.event_mut().counter += 2; + }); + world.add_observer(|mut trigger: Trigger| { + trigger.event_mut().counter += 4; + }); // This flush is required for the last observer to be called when triggering the event, - // due to `World::observe` returning `WorldEntityMut`. + // due to `World::add_observer` returning `WorldEntityMut`. world.flush(); let mut event = EventWithData { counter: 0 }; @@ -743,8 +786,8 @@ mod tests { let mut world = World::new(); world.init_resource::(); - world.observe(|_: Trigger, mut res: ResMut| res.observed("add_1")); - world.observe(|_: Trigger, mut res: ResMut| res.observed("add_2")); + world.add_observer(|_: Trigger, mut res: ResMut| res.observed("add_1")); + world.add_observer(|_: Trigger, mut res: ResMut| res.observed("add_2")); world.spawn(A).flush(); assert_eq!(vec!["add_1", "add_2"], world.resource::().0); @@ -782,7 +825,9 @@ mod tests { world.register_component::(); world.register_component::(); - world.observe(|_: Trigger, mut res: ResMut| res.observed("add_ab")); + world.add_observer(|_: Trigger, mut res: ResMut| { + res.observed("add_ab"); + }); let entity = world.spawn(A).id(); world.entity_mut(entity).insert(B); @@ -795,7 +840,9 @@ mod tests { let mut world = World::new(); let observer = world - .observe(|_: Trigger| panic!("Observer triggered after being despawned.")) + .add_observer(|_: Trigger| { + panic!("Observer triggered after being despawned.") + }) .id(); world.despawn(observer); world.spawn(A).flush(); @@ -809,10 +856,14 @@ mod tests { let entity = world.spawn((A, B)).flush(); - world.observe(|_: Trigger, mut res: ResMut| res.observed("remove_a")); + world.add_observer(|_: Trigger, mut res: ResMut| { + res.observed("remove_a"); + }); let observer = world - .observe(|_: Trigger| panic!("Observer triggered after being despawned.")) + .add_observer(|_: Trigger| { + panic!("Observer triggered after being despawned.") + }) .flush(); world.despawn(observer); @@ -826,7 +877,9 @@ mod tests { let mut world = World::new(); world.init_resource::(); - world.observe(|_: Trigger, mut res: ResMut| res.observed("add_ab")); + world.add_observer(|_: Trigger, mut res: ResMut| { + res.observed("add_ab"); + }); world.spawn((A, B)).flush(); assert_eq!(vec!["add_ab"], world.resource::().0); @@ -839,8 +892,8 @@ mod tests { world .spawn_empty() - .observe_entity(|_: Trigger| panic!("Trigger routed to non-targeted entity.")); - world.observe(move |obs: Trigger, mut res: ResMut| { + .observe(|_: Trigger| panic!("Trigger routed to non-targeted entity.")); + world.add_observer(move |obs: Trigger, mut res: ResMut| { assert_eq!(obs.entity(), Entity::PLACEHOLDER); res.observed("event_a"); }); @@ -860,12 +913,12 @@ mod tests { world .spawn_empty() - .observe_entity(|_: Trigger| panic!("Trigger routed to non-targeted entity.")); + .observe(|_: Trigger| panic!("Trigger routed to non-targeted entity.")); let entity = world .spawn_empty() - .observe_entity(|_: Trigger, mut res: ResMut| res.observed("a_1")) + .observe(|_: Trigger, mut res: ResMut| res.observed("a_1")) .id(); - world.observe(move |obs: Trigger, mut res: ResMut| { + world.add_observer(move |obs: Trigger, mut res: ResMut| { assert_eq!(obs.entity(), entity); res.observed("a_2"); }); @@ -931,14 +984,14 @@ mod tests { let parent = world .spawn_empty() - .observe_entity(|_: Trigger, mut res: ResMut| { + .observe(|_: Trigger, mut res: ResMut| { res.observed("parent"); }) .id(); let child = world .spawn(Parent(parent)) - .observe_entity(|_: Trigger, mut res: ResMut| { + .observe(|_: Trigger, mut res: ResMut| { res.observed("child"); }) .id(); @@ -958,14 +1011,14 @@ mod tests { let parent = world .spawn_empty() - .observe_entity(|_: Trigger, mut res: ResMut| { + .observe(|_: Trigger, mut res: ResMut| { res.observed("parent"); }) .id(); let child = world .spawn(Parent(parent)) - .observe_entity(|_: Trigger, mut res: ResMut| { + .observe(|_: Trigger, mut res: ResMut| { res.observed("child"); }) .id(); @@ -988,14 +1041,14 @@ mod tests { let parent = world .spawn_empty() - .observe_entity(|_: Trigger, mut res: ResMut| { + .observe(|_: Trigger, mut res: ResMut| { res.observed("parent"); }) .id(); let child = world .spawn(Parent(parent)) - .observe_entity(|_: Trigger, mut res: ResMut| { + .observe(|_: Trigger, mut res: ResMut| { res.observed("child"); }) .id(); @@ -1018,14 +1071,14 @@ mod tests { let parent = world .spawn_empty() - .observe_entity(|_: Trigger, mut res: ResMut| { + .observe(|_: Trigger, mut res: ResMut| { res.observed("parent"); }) .id(); let child = world .spawn(Parent(parent)) - .observe_entity( + .observe( |mut trigger: Trigger, mut res: ResMut| { res.observed("child"); trigger.propagate(false); @@ -1048,21 +1101,21 @@ mod tests { let parent = world .spawn_empty() - .observe_entity(|_: Trigger, mut res: ResMut| { + .observe(|_: Trigger, mut res: ResMut| { res.observed("parent"); }) .id(); let child_a = world .spawn(Parent(parent)) - .observe_entity(|_: Trigger, mut res: ResMut| { + .observe(|_: Trigger, mut res: ResMut| { res.observed("child_a"); }) .id(); let child_b = world .spawn(Parent(parent)) - .observe_entity(|_: Trigger, mut res: ResMut| { + .observe(|_: Trigger, mut res: ResMut| { res.observed("child_b"); }) .id(); @@ -1085,7 +1138,7 @@ mod tests { let entity = world .spawn_empty() - .observe_entity(|_: Trigger, mut res: ResMut| { + .observe(|_: Trigger, mut res: ResMut| { res.observed("event"); }) .id(); @@ -1105,14 +1158,14 @@ mod tests { let parent_a = world .spawn_empty() - .observe_entity(|_: Trigger, mut res: ResMut| { + .observe(|_: Trigger, mut res: ResMut| { res.observed("parent_a"); }) .id(); let child_a = world .spawn(Parent(parent_a)) - .observe_entity( + .observe( |mut trigger: Trigger, mut res: ResMut| { res.observed("child_a"); trigger.propagate(false); @@ -1122,14 +1175,14 @@ mod tests { let parent_b = world .spawn_empty() - .observe_entity(|_: Trigger, mut res: ResMut| { + .observe(|_: Trigger, mut res: ResMut| { res.observed("parent_b"); }) .id(); let child_b = world .spawn(Parent(parent_b)) - .observe_entity(|_: Trigger, mut res: ResMut| { + .observe(|_: Trigger, mut res: ResMut| { res.observed("child_b"); }) .id(); @@ -1150,7 +1203,9 @@ mod tests { let mut world = World::new(); world.init_resource::(); - world.observe(|_: Trigger, mut res: ResMut| res.observed("event")); + world.add_observer(|_: Trigger, mut res: ResMut| { + res.observed("event"); + }); let grandparent = world.spawn_empty().id(); let parent = world.spawn(Parent(grandparent)).id(); @@ -1169,7 +1224,7 @@ mod tests { let mut world = World::new(); world.init_resource::(); - world.observe( + world.add_observer( |trigger: Trigger, query: Query<&A>, mut res: ResMut| { if query.get(trigger.entity()).is_ok() { res.observed("event"); @@ -1196,7 +1251,7 @@ mod tests { let mut world = World::new(); // Observe the removal of A - this will run during despawn - world.observe(|_: Trigger, mut cmd: Commands| { + world.add_observer(|_: Trigger, mut cmd: Commands| { // Spawn a new entity - this reserves a new ID and requires a flush // afterward before Entities::free can be called. cmd.spawn_empty(); @@ -1224,7 +1279,7 @@ mod tests { let mut world = World::new(); // This fails because `ResA` is not present in the world - world.observe(|_: Trigger, _: Res, mut commands: Commands| { + world.add_observer(|_: Trigger, _: Res, mut commands: Commands| { commands.insert_resource(ResB); }); world.trigger(EventA); @@ -1241,7 +1296,7 @@ mod tests { struct ResA; let mut world = World::new(); - world.observe( + world.add_observer( |_: Trigger, mut params: ParamSet<(Query, Commands)>| { params.p1().insert_resource(ResA); }, diff --git a/crates/bevy_ecs/src/observer/runner.rs b/crates/bevy_ecs/src/observer/runner.rs index 02340b6128289..948783ea19ff1 100644 --- a/crates/bevy_ecs/src/observer/runner.rs +++ b/crates/bevy_ecs/src/observer/runner.rs @@ -111,7 +111,7 @@ pub type ObserverRunner = fn(DeferredWorld, ObserverTrigger, PtrMut, propagate: /// message: String, /// } /// -/// world.observe(|trigger: Trigger| { +/// world.add_observer(|trigger: Trigger| { /// println!("{}", trigger.event().message); /// }); /// @@ -124,7 +124,7 @@ pub type ObserverRunner = fn(DeferredWorld, ObserverTrigger, PtrMut, propagate: /// }); /// ``` /// -/// Notice that we used [`World::observe`]. This is just a shorthand for spawning an [`Observer`] manually: +/// Notice that we used [`World::add_observer`]. This is just a shorthand for spawning an [`Observer`] manually: /// /// ``` /// # use bevy_ecs::prelude::*; @@ -132,7 +132,7 @@ pub type ObserverRunner = fn(DeferredWorld, ObserverTrigger, PtrMut, propagate: /// # #[derive(Event)] /// # struct Speak; /// // These are functionally the same: -/// world.observe(|trigger: Trigger| {}); +/// world.add_observer(|trigger: Trigger| {}); /// world.spawn(Observer::new(|trigger: Trigger| {})); /// ``` /// @@ -145,7 +145,7 @@ pub type ObserverRunner = fn(DeferredWorld, ObserverTrigger, PtrMut, propagate: /// # struct PrintNames; /// # #[derive(Component, Debug)] /// # struct Name; -/// world.observe(|trigger: Trigger, names: Query<&Name>| { +/// world.add_observer(|trigger: Trigger, names: Query<&Name>| { /// for name in &names { /// println!("{name:?}"); /// } @@ -163,7 +163,7 @@ pub type ObserverRunner = fn(DeferredWorld, ObserverTrigger, PtrMut, propagate: /// # struct SpawnThing; /// # #[derive(Component, Debug)] /// # struct Thing; -/// world.observe(|trigger: Trigger, mut commands: Commands| { +/// world.add_observer(|trigger: Trigger, mut commands: Commands| { /// commands.spawn(Thing); /// }); /// ``` @@ -177,7 +177,7 @@ pub type ObserverRunner = fn(DeferredWorld, ObserverTrigger, PtrMut, propagate: /// # struct A; /// # #[derive(Event)] /// # struct B; -/// world.observe(|trigger: Trigger, mut commands: Commands| { +/// world.add_observer(|trigger: Trigger, mut commands: Commands| { /// commands.trigger(B); /// }); /// ``` @@ -195,7 +195,7 @@ pub type ObserverRunner = fn(DeferredWorld, ObserverTrigger, PtrMut, propagate: /// #[derive(Event)] /// struct Explode; /// -/// world.observe(|trigger: Trigger, mut commands: Commands| { +/// world.add_observer(|trigger: Trigger, mut commands: Commands| { /// println!("Entity {:?} goes BOOM!", trigger.entity()); /// commands.entity(trigger.entity()).despawn(); /// }); @@ -228,12 +228,12 @@ pub type ObserverRunner = fn(DeferredWorld, ObserverTrigger, PtrMut, propagate: /// # let e2 = world.spawn_empty().id(); /// # #[derive(Event)] /// # struct Explode; -/// world.entity_mut(e1).observe_entity(|trigger: Trigger, mut commands: Commands| { +/// world.entity_mut(e1).observe(|trigger: Trigger, mut commands: Commands| { /// println!("Boom!"); /// commands.entity(trigger.entity()).despawn(); /// }); /// -/// world.entity_mut(e2).observe_entity(|trigger: Trigger, mut commands: Commands| { +/// world.entity_mut(e2).observe(|trigger: Trigger, mut commands: Commands| { /// println!("The explosion fizzles! This entity is immune!"); /// }); /// ``` @@ -241,7 +241,7 @@ pub type ObserverRunner = fn(DeferredWorld, ObserverTrigger, PtrMut, propagate: /// If all entities watched by a given [`Observer`] are despawned, the [`Observer`] entity will also be despawned. /// This protects against observer "garbage" building up over time. /// -/// The examples above calling [`EntityWorldMut::observe_entity`] to add entity-specific observer logic are (once again) +/// The examples above calling [`EntityWorldMut::observe`] to add entity-specific observer logic are (once again) /// just shorthand for spawning an [`Observer`] directly: /// /// ``` diff --git a/crates/bevy_ecs/src/system/commands/mod.rs b/crates/bevy_ecs/src/system/commands/mod.rs index 35f3aad376529..b4c6d46ff6c38 100644 --- a/crates/bevy_ecs/src/system/commands/mod.rs +++ b/crates/bevy_ecs/src/system/commands/mod.rs @@ -832,8 +832,13 @@ impl<'w, 's> Commands<'w, 's> { self.queue(TriggerEvent { event, targets }); } - /// Spawns an [`Observer`] and returns the [`EntityCommands`] associated with the entity that stores the observer. - pub fn observe( + /// Spawns an [`Observer`] and returns the [`EntityCommands`] associated + /// with the entity that stores the observer. + /// + /// **Calling [`observe`](EntityCommands::observe) on the returned + /// [`EntityCommands`] will observe the observer itself, which you very + /// likely do not want.** + pub fn add_observer( &mut self, observer: impl IntoObserverSystem, ) -> EntityCommands { @@ -1923,7 +1928,7 @@ fn observe( ) -> impl EntityCommand { move |entity: Entity, world: &mut World| { if let Ok(mut entity) = world.get_entity_mut(entity) { - entity.observe_entity(observer); + entity.observe(observer); } } } diff --git a/crates/bevy_ecs/src/system/observer_system.rs b/crates/bevy_ecs/src/system/observer_system.rs index 55173ccf4f22a..aa247d493964a 100644 --- a/crates/bevy_ecs/src/system/observer_system.rs +++ b/crates/bevy_ecs/src/system/observer_system.rs @@ -70,7 +70,7 @@ mod tests { fn b() {} let mut world = World::new(); - world.observe(a.pipe(b)); + world.add_observer(a.pipe(b)); } #[test] @@ -81,6 +81,6 @@ mod tests { fn b(_: In) {} let mut world = World::new(); - world.observe(a.pipe(b)); + world.add_observer(a.pipe(b)); } } diff --git a/crates/bevy_ecs/src/world/entity_ref.rs b/crates/bevy_ecs/src/world/entity_ref.rs index 1097dba575644..7b8dc9465b57e 100644 --- a/crates/bevy_ecs/src/world/entity_ref.rs +++ b/crates/bevy_ecs/src/world/entity_ref.rs @@ -1854,7 +1854,7 @@ impl<'w> EntityWorldMut<'w> { /// Creates an [`Observer`] listening for events of type `E` targeting this entity. /// In order to trigger the callback the entity must also match the query when the event is fired. - pub fn observe_entity( + pub fn observe( &mut self, observer: impl IntoObserverSystem, ) -> &mut Self { diff --git a/crates/bevy_pbr/src/lib.rs b/crates/bevy_pbr/src/lib.rs index f2eb51a33e91c..997a0b99caac3 100644 --- a/crates/bevy_pbr/src/lib.rs +++ b/crates/bevy_pbr/src/lib.rs @@ -458,8 +458,10 @@ impl Plugin for PbrPlugin { ) .init_resource::(); - render_app.world_mut().observe(add_light_view_entities); - render_app.world_mut().observe(remove_light_view_entities); + render_app.world_mut().add_observer(add_light_view_entities); + render_app + .world_mut() + .add_observer(remove_light_view_entities); let shadow_pass_node = ShadowPassNode::new(render_app.world_mut()); let mut graph = render_app.world_mut().resource_mut::(); diff --git a/crates/bevy_picking/src/events.rs b/crates/bevy_picking/src/events.rs index 9cbec38592e14..c61ca42aea4c9 100644 --- a/crates/bevy_picking/src/events.rs +++ b/crates/bevy_picking/src/events.rs @@ -11,7 +11,7 @@ //! # use bevy_picking::prelude::*; //! # let mut world = World::default(); //! world.spawn_empty() -//! .observe_entity(|trigger: Trigger>| { +//! .observe(|trigger: Trigger>| { //! println!("I am being hovered over"); //! }); //! ``` diff --git a/crates/bevy_picking/src/lib.rs b/crates/bevy_picking/src/lib.rs index c1ec7a49e9d96..df6d37ca004ff 100644 --- a/crates/bevy_picking/src/lib.rs +++ b/crates/bevy_picking/src/lib.rs @@ -15,7 +15,7 @@ //! # struct MyComponent; //! # let mut world = World::new(); //! world.spawn(MyComponent) -//! .observe_entity(|mut trigger: Trigger>| { +//! .observe(|mut trigger: Trigger>| { //! // Get the underlying event type //! let click_event: &Pointer = trigger.event(); //! // Stop the event from bubbling up the entity hierarchjy diff --git a/crates/bevy_render/src/sync_world.rs b/crates/bevy_render/src/sync_world.rs index 3ee9f25fbdbe5..d32462e56f320 100644 --- a/crates/bevy_render/src/sync_world.rs +++ b/crates/bevy_render/src/sync_world.rs @@ -85,12 +85,12 @@ pub struct SyncWorldPlugin; impl Plugin for SyncWorldPlugin { fn build(&self, app: &mut bevy_app::App) { app.init_resource::(); - app.observe( + app.add_observer( |trigger: Trigger, mut pending: ResMut| { pending.push(EntityRecord::Added(trigger.entity())); }, ); - app.observe( + app.add_observer( |trigger: Trigger, mut pending: ResMut, query: Query<&RenderEntity>| { @@ -248,12 +248,12 @@ mod tests { let mut render_world = World::new(); main_world.init_resource::(); - main_world.observe( + main_world.add_observer( |trigger: Trigger, mut pending: ResMut| { pending.push(EntityRecord::Added(trigger.entity())); }, ); - main_world.observe( + main_world.add_observer( |trigger: Trigger, mut pending: ResMut, query: Query<&RenderEntity>| { diff --git a/crates/bevy_scene/src/scene_spawner.rs b/crates/bevy_scene/src/scene_spawner.rs index 92c3e41571ed0..e192aa4324be8 100644 --- a/crates/bevy_scene/src/scene_spawner.rs +++ b/crates/bevy_scene/src/scene_spawner.rs @@ -581,7 +581,7 @@ mod tests { fn observe_trigger(app: &mut App, scene_id: InstanceId, scene_entity: Entity) { // Add observer - app.world_mut().observe( + app.world_mut().add_observer( move |trigger: Trigger, scene_spawner: Res, mut trigger_count: ResMut| { diff --git a/crates/bevy_winit/src/cursor.rs b/crates/bevy_winit/src/cursor.rs index 297598630b1c7..524a6ceb3c493 100644 --- a/crates/bevy_winit/src/cursor.rs +++ b/crates/bevy_winit/src/cursor.rs @@ -31,7 +31,7 @@ impl Plugin for CursorPlugin { .init_resource::() .add_systems(Last, update_cursors); - app.observe(on_remove_cursor_icon); + app.add_observer(on_remove_cursor_icon); } } diff --git a/examples/animation/animated_fox.rs b/examples/animation/animated_fox.rs index fcd5dd65f2405..b0bcbac3c5755 100644 --- a/examples/animation/animated_fox.rs +++ b/examples/animation/animated_fox.rs @@ -24,7 +24,7 @@ fn main() { .add_systems(Startup, setup) .add_systems(Update, setup_scene_once_loaded.before(animate_targets)) .add_systems(Update, (keyboard_animation_control, simulate_particles)) - .observe(observe_on_step) + .add_observer(observe_on_step) .run(); } diff --git a/examples/ecs/observer_propagation.rs b/examples/ecs/observer_propagation.rs index d193348cd9cf0..ce5911ebb2117 100644 --- a/examples/ecs/observer_propagation.rs +++ b/examples/ecs/observer_propagation.rs @@ -14,7 +14,7 @@ fn main() { attack_armor.run_if(on_timer(Duration::from_millis(200))), ) // Add a global observer that will emit a line whenever an attack hits an entity. - .observe(attack_hits) + .add_observer(attack_hits) .run(); } diff --git a/examples/ecs/observers.rs b/examples/ecs/observers.rs index 58b5e4e13959d..e0602f3a068cd 100644 --- a/examples/ecs/observers.rs +++ b/examples/ecs/observers.rs @@ -15,7 +15,7 @@ fn main() { .add_systems(Update, (draw_shapes, handle_click)) // Observers are systems that run when an event is "triggered". This observer runs whenever // `ExplodeMines` is triggered. - .observe( + .add_observer( |trigger: Trigger, mines: Query<&Mine>, index: Res, @@ -35,10 +35,10 @@ fn main() { }, ) // This observer runs whenever the `Mine` component is added to an entity, and places it in a simple spatial index. - .observe(on_add_mine) + .add_observer(on_add_mine) // This observer runs whenever the `Mine` component is removed from an entity (including despawning it) // and removes it from the spatial index. - .observe(on_remove_mine) + .add_observer(on_remove_mine) .run(); } diff --git a/examples/ecs/removal_detection.rs b/examples/ecs/removal_detection.rs index 3af28fe6d3de8..1d16631b05efd 100644 --- a/examples/ecs/removal_detection.rs +++ b/examples/ecs/removal_detection.rs @@ -17,7 +17,7 @@ fn main() { // This system will remove a component after two seconds. .add_systems(Update, remove_component) // This observer will react to the removal of the component. - .observe(react_on_removal) + .add_observer(react_on_removal) .run(); }