Rename trigger.entity() to trigger.target() (#16716)

# Objective

- A `Trigger` has multiple associated `Entity`s - the entity observing
the event, and the entity that was targeted by the event.
- The field `entity: Entity` encodes no semantic information about what
the entity is used for, you can already tell that it's an `Entity` by
the type signature!

## Solution

- Rename `trigger.entity()` to `trigger.target()`

---

## Changelog

- `Trigger`s are associated with multiple entities. `Trigger::entity()`
has been renamed to `Trigger::target()` to reflect the semantics of the
entity being returned.

## Migration Guide

- Rename `Trigger::entity()` to `Trigger::target()`.
- Rename `ObserverTrigger::entity` to `ObserverTrigger::target`
This commit is contained in:
Aevyrie 2024-12-08 13:55:09 -08:00 committed by GitHub
parent 1d3950a82a
commit 61b98ec80f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 73 additions and 60 deletions

View file

@ -340,8 +340,8 @@ let mut world = World::new();
let entity = world.spawn_empty().id(); let entity = world.spawn_empty().id();
world.add_observer(|trigger: Trigger<Explode>, mut commands: Commands| { world.add_observer(|trigger: Trigger<Explode>, mut commands: Commands| {
println!("Entity {:?} goes BOOM!", trigger.entity()); println!("Entity {:?} goes BOOM!", trigger.target());
commands.entity(trigger.entity()).despawn(); commands.entity(trigger.target()).despawn();
}); });
world.flush(); world.flush();

View file

@ -67,9 +67,22 @@ impl<'w, E, B: Bundle> Trigger<'w, E, B> {
Ptr::from(&self.event) Ptr::from(&self.event)
} }
/// Returns the [`Entity`] that triggered the observer, could be [`Entity::PLACEHOLDER`]. /// Returns the [`Entity`] that was targeted by the `event` that triggered this observer. It may
pub fn entity(&self) -> Entity { /// be [`Entity::PLACEHOLDER`].
self.trigger.entity ///
/// Observable events can target specific entities. When those events fire, they will trigger
/// any observers on the targeted entities. In this case, the `target()` and `observer()` are
/// the same, because the observer that was triggered is attached to the entity that was
/// targeted by the event.
///
/// However, it is also possible for those events to bubble up the entity hierarchy and trigger
/// observers on *different* entities, or trigger a global observer. In these cases, the
/// observing entity is *different* from the entity being targeted by the event.
///
/// This is an important distinction: the entity reacting to an event is not always the same as
/// the entity triggered by the event.
pub fn target(&self) -> Entity {
self.trigger.target
} }
/// Returns the components that triggered the observer, out of the /// Returns the components that triggered the observer, out of the
@ -207,7 +220,7 @@ pub struct ObserverTrigger {
/// The [`ComponentId`]s the trigger targeted. /// The [`ComponentId`]s the trigger targeted.
components: SmallVec<[ComponentId; 2]>, components: SmallVec<[ComponentId; 2]>,
/// The entity the trigger targeted. /// The entity the trigger targeted.
pub entity: Entity, pub target: Entity,
} }
impl ObserverTrigger { impl ObserverTrigger {
@ -277,7 +290,7 @@ impl Observers {
pub(crate) fn invoke<T>( pub(crate) fn invoke<T>(
mut world: DeferredWorld, mut world: DeferredWorld,
event_type: ComponentId, event_type: ComponentId,
entity: Entity, target: Entity,
components: impl Iterator<Item = ComponentId> + Clone, components: impl Iterator<Item = ComponentId> + Clone,
data: &mut T, data: &mut T,
propagate: &mut bool, propagate: &mut bool,
@ -304,7 +317,7 @@ impl Observers {
observer, observer,
event_type, event_type,
components: components.clone().collect(), components: components.clone().collect(),
entity, target,
}, },
data.into(), data.into(),
propagate, propagate,
@ -314,8 +327,8 @@ impl Observers {
observers.map.iter().for_each(&mut trigger_observer); observers.map.iter().for_each(&mut trigger_observer);
// Trigger entity observers listening for this kind of trigger // Trigger entity observers listening for this kind of trigger
if entity != Entity::PLACEHOLDER { if target != Entity::PLACEHOLDER {
if let Some(map) = observers.entity_observers.get(&entity) { if let Some(map) = observers.entity_observers.get(&target) {
map.iter().for_each(&mut trigger_observer); map.iter().for_each(&mut trigger_observer);
} }
} }
@ -328,8 +341,8 @@ impl Observers {
.iter() .iter()
.for_each(&mut trigger_observer); .for_each(&mut trigger_observer);
if entity != Entity::PLACEHOLDER { if target != Entity::PLACEHOLDER {
if let Some(map) = component_observers.entity_map.get(&entity) { if let Some(map) = component_observers.entity_map.get(&target) {
map.iter().for_each(&mut trigger_observer); map.iter().for_each(&mut trigger_observer);
} }
} }
@ -733,20 +746,20 @@ mod tests {
world.add_observer( world.add_observer(
|obs: Trigger<OnAdd, A>, mut res: ResMut<Order>, mut commands: Commands| { |obs: Trigger<OnAdd, A>, mut res: ResMut<Order>, mut commands: Commands| {
res.observed("add_a"); res.observed("add_a");
commands.entity(obs.entity()).insert(B); commands.entity(obs.target()).insert(B);
}, },
); );
world.add_observer( world.add_observer(
|obs: Trigger<OnRemove, A>, mut res: ResMut<Order>, mut commands: Commands| { |obs: Trigger<OnRemove, A>, mut res: ResMut<Order>, mut commands: Commands| {
res.observed("remove_a"); res.observed("remove_a");
commands.entity(obs.entity()).remove::<B>(); commands.entity(obs.target()).remove::<B>();
}, },
); );
world.add_observer( world.add_observer(
|obs: Trigger<OnAdd, B>, mut res: ResMut<Order>, mut commands: Commands| { |obs: Trigger<OnAdd, B>, mut res: ResMut<Order>, mut commands: Commands| {
res.observed("add_b"); res.observed("add_b");
commands.entity(obs.entity()).remove::<A>(); commands.entity(obs.target()).remove::<A>();
}, },
); );
world.add_observer(|_: Trigger<OnRemove, B>, mut res: ResMut<Order>| { world.add_observer(|_: Trigger<OnRemove, B>, mut res: ResMut<Order>| {
@ -915,7 +928,7 @@ mod tests {
.spawn_empty() .spawn_empty()
.observe(|_: Trigger<EventA>| panic!("Trigger routed to non-targeted entity.")); .observe(|_: Trigger<EventA>| panic!("Trigger routed to non-targeted entity."));
world.add_observer(move |obs: Trigger<EventA>, mut res: ResMut<Order>| { world.add_observer(move |obs: Trigger<EventA>, mut res: ResMut<Order>| {
assert_eq!(obs.entity(), Entity::PLACEHOLDER); assert_eq!(obs.target(), Entity::PLACEHOLDER);
res.observed("event_a"); res.observed("event_a");
}); });
@ -940,7 +953,7 @@ mod tests {
.observe(|_: Trigger<EventA>, mut res: ResMut<Order>| res.observed("a_1")) .observe(|_: Trigger<EventA>, mut res: ResMut<Order>| res.observed("a_1"))
.id(); .id();
world.add_observer(move |obs: Trigger<EventA>, mut res: ResMut<Order>| { world.add_observer(move |obs: Trigger<EventA>, mut res: ResMut<Order>| {
assert_eq!(obs.entity(), entity); assert_eq!(obs.target(), entity);
res.observed("a_2"); res.observed("a_2");
}); });
@ -1247,7 +1260,7 @@ mod tests {
world.add_observer( world.add_observer(
|trigger: Trigger<EventPropagating>, query: Query<&A>, mut res: ResMut<Order>| { |trigger: Trigger<EventPropagating>, query: Query<&A>, mut res: ResMut<Order>| {
if query.get(trigger.entity()).is_ok() { if query.get(trigger.target()).is_ok() {
res.observed("event"); res.observed("event");
} }
}, },

View file

@ -197,8 +197,8 @@ pub type ObserverRunner = fn(DeferredWorld, ObserverTrigger, PtrMut, propagate:
/// struct Explode; /// struct Explode;
/// ///
/// world.add_observer(|trigger: Trigger<Explode>, mut commands: Commands| { /// world.add_observer(|trigger: Trigger<Explode>, mut commands: Commands| {
/// println!("Entity {:?} goes BOOM!", trigger.entity()); /// println!("Entity {:?} goes BOOM!", trigger.target());
/// commands.entity(trigger.entity()).despawn(); /// commands.entity(trigger.target()).despawn();
/// }); /// });
/// ///
/// world.flush(); /// world.flush();
@ -231,7 +231,7 @@ pub type ObserverRunner = fn(DeferredWorld, ObserverTrigger, PtrMut, propagate:
/// # struct Explode; /// # struct Explode;
/// world.entity_mut(e1).observe(|trigger: Trigger<Explode>, mut commands: Commands| { /// world.entity_mut(e1).observe(|trigger: Trigger<Explode>, mut commands: Commands| {
/// println!("Boom!"); /// println!("Boom!");
/// commands.entity(trigger.entity()).despawn(); /// commands.entity(trigger.target()).despawn();
/// }); /// });
/// ///
/// world.entity_mut(e2).observe(|trigger: Trigger<Explode>, mut commands: Commands| { /// world.entity_mut(e2).observe(|trigger: Trigger<Explode>, mut commands: Commands| {

View file

@ -508,13 +508,13 @@ impl<'w> DeferredWorld<'w> {
pub(crate) unsafe fn trigger_observers( pub(crate) unsafe fn trigger_observers(
&mut self, &mut self,
event: ComponentId, event: ComponentId,
entity: Entity, target: Entity,
components: impl Iterator<Item = ComponentId> + Clone, components: impl Iterator<Item = ComponentId> + Clone,
) { ) {
Observers::invoke::<_>( Observers::invoke::<_>(
self.reborrow(), self.reborrow(),
event, event,
entity, target,
components, components,
&mut (), &mut (),
&mut false, &mut false,
@ -529,7 +529,7 @@ impl<'w> DeferredWorld<'w> {
pub(crate) unsafe fn trigger_observers_with_data<E, T>( pub(crate) unsafe fn trigger_observers_with_data<E, T>(
&mut self, &mut self,
event: ComponentId, event: ComponentId,
mut entity: Entity, mut target: Entity,
components: &[ComponentId], components: &[ComponentId],
data: &mut E, data: &mut E,
mut propagate: bool, mut propagate: bool,
@ -540,7 +540,7 @@ impl<'w> DeferredWorld<'w> {
Observers::invoke::<_>( Observers::invoke::<_>(
self.reborrow(), self.reborrow(),
event, event,
entity, target,
components.iter().copied(), components.iter().copied(),
data, data,
&mut propagate, &mut propagate,
@ -549,12 +549,12 @@ impl<'w> DeferredWorld<'w> {
break; break;
} }
if let Some(traverse_to) = self if let Some(traverse_to) = self
.get_entity(entity) .get_entity(target)
.ok() .ok()
.and_then(|entity| entity.get_components::<T>()) .and_then(|entity| entity.get_components::<T>())
.and_then(|item| T::traverse(item, data)) .and_then(|item| T::traverse(item, data))
{ {
entity = traverse_to; target = traverse_to;
} else { } else {
break; break;
} }

View file

@ -4703,7 +4703,7 @@ mod tests {
let entity = world let entity = world
.spawn_empty() .spawn_empty()
.observe(|trigger: Trigger<TestEvent>, mut commands: Commands| { .observe(|trigger: Trigger<TestEvent>, mut commands: Commands| {
commands.entity(trigger.entity()).insert(TestComponent(0)); commands.entity(trigger.target()).insert(TestComponent(0));
}) })
.id(); .id();
@ -4725,7 +4725,7 @@ mod tests {
let mut world = World::new(); let mut world = World::new();
world.add_observer( world.add_observer(
|trigger: Trigger<OnAdd, TestComponent>, mut commands: Commands| { |trigger: Trigger<OnAdd, TestComponent>, mut commands: Commands| {
commands.entity(trigger.entity()).despawn(); commands.entity(trigger.target()).despawn();
}, },
); );
let entity = world.spawn_empty().id(); let entity = world.spawn_empty().id();

View file

@ -496,7 +496,7 @@ pub(crate) fn add_light_view_entities(
trigger: Trigger<OnAdd, (ExtractedDirectionalLight, ExtractedPointLight)>, trigger: Trigger<OnAdd, (ExtractedDirectionalLight, ExtractedPointLight)>,
mut commands: Commands, mut commands: Commands,
) { ) {
if let Some(mut v) = commands.get_entity(trigger.entity()) { if let Some(mut v) = commands.get_entity(trigger.target()) {
v.insert(LightViewEntities::default()); v.insert(LightViewEntities::default());
} }
} }
@ -506,7 +506,7 @@ pub(crate) fn extracted_light_removed(
trigger: Trigger<OnRemove, (ExtractedDirectionalLight, ExtractedPointLight)>, trigger: Trigger<OnRemove, (ExtractedDirectionalLight, ExtractedPointLight)>,
mut commands: Commands, mut commands: Commands,
) { ) {
if let Some(mut v) = commands.get_entity(trigger.entity()) { if let Some(mut v) = commands.get_entity(trigger.target()) {
v.remove::<LightViewEntities>(); v.remove::<LightViewEntities>();
} }
} }
@ -516,7 +516,7 @@ pub(crate) fn remove_light_view_entities(
query: Query<&LightViewEntities>, query: Query<&LightViewEntities>,
mut commands: Commands, mut commands: Commands,
) { ) {
if let Ok(entities) = query.get(trigger.entity()) { if let Ok(entities) = query.get(trigger.target()) {
for v in entities.0.values() { for v in entities.0.values() {
for e in v.iter().copied() { for e in v.iter().copied() {
if let Some(mut v) = commands.get_entity(e) { if let Some(mut v) = commands.get_entity(e) {

View file

@ -49,13 +49,13 @@
//! // Spawn your entity here, e.g. a Mesh. //! // Spawn your entity here, e.g. a Mesh.
//! // When dragged, mutate the `Transform` component on the dragged target entity: //! // When dragged, mutate the `Transform` component on the dragged target entity:
//! .observe(|trigger: Trigger<Pointer<Drag>>, mut transforms: Query<&mut Transform>| { //! .observe(|trigger: Trigger<Pointer<Drag>>, mut transforms: Query<&mut Transform>| {
//! let mut transform = transforms.get_mut(trigger.entity()).unwrap(); //! let mut transform = transforms.get_mut(trigger.target()).unwrap();
//! let drag = trigger.event(); //! let drag = trigger.event();
//! transform.rotate_local_y(drag.delta.x / 50.0); //! transform.rotate_local_y(drag.delta.x / 50.0);
//! }) //! })
//! .observe(|trigger: Trigger<Pointer<Click>>, mut commands: Commands| { //! .observe(|trigger: Trigger<Pointer<Click>>, mut commands: Commands| {
//! println!("Entity {:?} goes BOOM!", trigger.entity()); //! println!("Entity {:?} goes BOOM!", trigger.target());
//! commands.entity(trigger.entity()).despawn(); //! commands.entity(trigger.target()).despawn();
//! }) //! })
//! .observe(|trigger: Trigger<Pointer<Over>>, mut events: EventWriter<Greeting>| { //! .observe(|trigger: Trigger<Pointer<Over>>, mut events: EventWriter<Greeting>| {
//! events.send(Greeting); //! events.send(Greeting);

View file

@ -93,14 +93,14 @@ impl Plugin for SyncWorldPlugin {
app.init_resource::<PendingSyncEntity>(); app.init_resource::<PendingSyncEntity>();
app.add_observer( app.add_observer(
|trigger: Trigger<OnAdd, SyncToRenderWorld>, mut pending: ResMut<PendingSyncEntity>| { |trigger: Trigger<OnAdd, SyncToRenderWorld>, mut pending: ResMut<PendingSyncEntity>| {
pending.push(EntityRecord::Added(trigger.entity())); pending.push(EntityRecord::Added(trigger.target()));
}, },
); );
app.add_observer( app.add_observer(
|trigger: Trigger<OnRemove, SyncToRenderWorld>, |trigger: Trigger<OnRemove, SyncToRenderWorld>,
mut pending: ResMut<PendingSyncEntity>, mut pending: ResMut<PendingSyncEntity>,
query: Query<&RenderEntity>| { query: Query<&RenderEntity>| {
if let Ok(e) = query.get(trigger.entity()) { if let Ok(e) = query.get(trigger.target()) {
pending.push(EntityRecord::Removed(*e)); pending.push(EntityRecord::Removed(*e));
}; };
}, },
@ -487,14 +487,14 @@ mod tests {
main_world.add_observer( main_world.add_observer(
|trigger: Trigger<OnAdd, SyncToRenderWorld>, mut pending: ResMut<PendingSyncEntity>| { |trigger: Trigger<OnAdd, SyncToRenderWorld>, mut pending: ResMut<PendingSyncEntity>| {
pending.push(EntityRecord::Added(trigger.entity())); pending.push(EntityRecord::Added(trigger.target()));
}, },
); );
main_world.add_observer( main_world.add_observer(
|trigger: Trigger<OnRemove, SyncToRenderWorld>, |trigger: Trigger<OnRemove, SyncToRenderWorld>,
mut pending: ResMut<PendingSyncEntity>, mut pending: ResMut<PendingSyncEntity>,
query: Query<&RenderEntity>| { query: Query<&RenderEntity>| {
if let Ok(e) = query.get(trigger.entity()) { if let Ok(e) = query.get(trigger.target()) {
pending.push(EntityRecord::Removed(*e)); pending.push(EntityRecord::Removed(*e));
}; };
}, },

View file

@ -594,7 +594,7 @@ mod tests {
"`SceneInstanceReady` contains the wrong `InstanceId`" "`SceneInstanceReady` contains the wrong `InstanceId`"
); );
assert_eq!( assert_eq!(
trigger.entity(), trigger.target(),
scene_entity, scene_entity,
"`SceneInstanceReady` triggered on the wrong parent entity" "`SceneInstanceReady` triggered on the wrong parent entity"
); );

View file

@ -185,7 +185,7 @@ fn update_cursors(
fn on_remove_cursor_icon(trigger: Trigger<OnRemove, CursorIcon>, mut commands: Commands) { fn on_remove_cursor_icon(trigger: Trigger<OnRemove, CursorIcon>, mut commands: Commands) {
// Use `try_insert` to avoid panic if the window is being destroyed. // Use `try_insert` to avoid panic if the window is being destroyed.
commands commands
.entity(trigger.entity()) .entity(trigger.target())
.try_insert(PendingCursor(Some(CursorSource::System( .try_insert(PendingCursor(Some(CursorSource::System(
convert_system_cursor_icon(SystemCursorIcon::Default), convert_system_cursor_icon(SystemCursorIcon::Default),
)))); ))));

View file

@ -48,7 +48,7 @@ fn observe_on_step(
transforms: Query<&GlobalTransform>, transforms: Query<&GlobalTransform>,
mut seeded_rng: ResMut<SeededRng>, mut seeded_rng: ResMut<SeededRng>,
) { ) {
let translation = transforms.get(trigger.entity()).unwrap().translation(); let translation = transforms.get(trigger.target()).unwrap().translation();
// Spawn a bunch of particles. // Spawn a bunch of particles.
for _ in 0..14 { for _ in 0..14 {
let horizontal = seeded_rng.0.gen::<Dir2>() * seeded_rng.0.gen_range(8.0..12.0); let horizontal = seeded_rng.0.gen::<Dir2>() * seeded_rng.0.gen_range(8.0..12.0);

View file

@ -78,14 +78,14 @@ fn attack_armor(entities: Query<Entity, With<Armor>>, mut commands: Commands) {
} }
fn attack_hits(trigger: Trigger<Attack>, name: Query<&Name>) { fn attack_hits(trigger: Trigger<Attack>, name: Query<&Name>) {
if let Ok(name) = name.get(trigger.entity()) { if let Ok(name) = name.get(trigger.target()) {
info!("Attack hit {}", name); info!("Attack hit {}", name);
} }
} }
/// A callback placed on [`Armor`], checking if it absorbed all the [`Attack`] damage. /// A callback placed on [`Armor`], checking if it absorbed all the [`Attack`] damage.
fn block_attack(mut trigger: Trigger<Attack>, armor: Query<(&Armor, &Name)>) { fn block_attack(mut trigger: Trigger<Attack>, armor: Query<(&Armor, &Name)>) {
let (armor, name) = armor.get(trigger.entity()).unwrap(); let (armor, name) = armor.get(trigger.target()).unwrap();
let attack = trigger.event_mut(); let attack = trigger.event_mut();
let damage = attack.damage.saturating_sub(**armor); let damage = attack.damage.saturating_sub(**armor);
if damage > 0 { if damage > 0 {
@ -110,14 +110,14 @@ fn take_damage(
mut app_exit: EventWriter<AppExit>, mut app_exit: EventWriter<AppExit>,
) { ) {
let attack = trigger.event(); let attack = trigger.event();
let (mut hp, name) = hp.get_mut(trigger.entity()).unwrap(); let (mut hp, name) = hp.get_mut(trigger.target()).unwrap();
**hp = hp.saturating_sub(attack.damage); **hp = hp.saturating_sub(attack.damage);
if **hp > 0 { if **hp > 0 {
info!("{} has {:.1} HP", name, hp.0); info!("{} has {:.1} HP", name, hp.0);
} else { } else {
warn!("💀 {} has died a gruesome death", name); warn!("💀 {} has died a gruesome death", name);
commands.entity(trigger.entity()).despawn_recursive(); commands.entity(trigger.target()).despawn_recursive();
app_exit.send(AppExit::Success); app_exit.send(AppExit::Success);
} }

View file

@ -117,12 +117,12 @@ fn on_add_mine(
query: Query<&Mine>, query: Query<&Mine>,
mut index: ResMut<SpatialIndex>, mut index: ResMut<SpatialIndex>,
) { ) {
let mine = query.get(trigger.entity()).unwrap(); let mine = query.get(trigger.target()).unwrap();
let tile = ( let tile = (
(mine.pos.x / CELL_SIZE).floor() as i32, (mine.pos.x / CELL_SIZE).floor() as i32,
(mine.pos.y / CELL_SIZE).floor() as i32, (mine.pos.y / CELL_SIZE).floor() as i32,
); );
index.map.entry(tile).or_default().insert(trigger.entity()); index.map.entry(tile).or_default().insert(trigger.target());
} }
// Remove despawned mines from our index // Remove despawned mines from our index
@ -131,19 +131,19 @@ fn on_remove_mine(
query: Query<&Mine>, query: Query<&Mine>,
mut index: ResMut<SpatialIndex>, mut index: ResMut<SpatialIndex>,
) { ) {
let mine = query.get(trigger.entity()).unwrap(); let mine = query.get(trigger.target()).unwrap();
let tile = ( let tile = (
(mine.pos.x / CELL_SIZE).floor() as i32, (mine.pos.x / CELL_SIZE).floor() as i32,
(mine.pos.y / CELL_SIZE).floor() as i32, (mine.pos.y / CELL_SIZE).floor() as i32,
); );
index.map.entry(tile).and_modify(|set| { index.map.entry(tile).and_modify(|set| {
set.remove(&trigger.entity()); set.remove(&trigger.target());
}); });
} }
fn explode_mine(trigger: Trigger<Explode>, query: Query<&Mine>, mut commands: Commands) { fn explode_mine(trigger: Trigger<Explode>, query: Query<&Mine>, mut commands: Commands) {
// If a triggered event is targeting a specific entity you can access it with `.entity()` // If a triggered event is targeting a specific entity you can access it with `.entity()`
let id = trigger.entity(); let id = trigger.target();
let Some(mut entity) = commands.get_entity(id) else { let Some(mut entity) = commands.get_entity(id) else {
return; return;
}; };

View file

@ -50,7 +50,7 @@ fn remove_component(
fn react_on_removal(trigger: Trigger<OnRemove, MyComponent>, mut query: Query<&mut Sprite>) { fn react_on_removal(trigger: Trigger<OnRemove, MyComponent>, mut query: Query<&mut Sprite>) {
// The `OnRemove` trigger was automatically called on the `Entity` that had its `MyComponent` removed. // The `OnRemove` trigger was automatically called on the `Entity` that had its `MyComponent` removed.
let entity = trigger.entity(); let entity = trigger.target();
if let Ok(mut sprite) = query.get_mut(entity) { if let Ok(mut sprite) = query.get_mut(entity) {
sprite.color = Color::srgb(0.5, 1., 1.); sprite.color = Color::srgb(0.5, 1., 1.);
} }

View file

@ -164,7 +164,7 @@ fn update_material_on<E>(
// versions of this observer, each triggered by a different event and with a different hardcoded // versions of this observer, each triggered by a different event and with a different hardcoded
// material. Instead, the event type is a generic, and the material is passed in. // material. Instead, the event type is a generic, and the material is passed in.
move |trigger, mut query| { move |trigger, mut query| {
if let Ok(mut material) = query.get_mut(trigger.entity()) { if let Ok(mut material) = query.get_mut(trigger.target()) {
material.0 = new_material.clone(); material.0 = new_material.clone();
} }
} }
@ -191,7 +191,7 @@ fn rotate(mut query: Query<&mut Transform, With<Shape>>, time: Res<Time>) {
/// An observer to rotate an entity when it is dragged /// An observer to rotate an entity when it is dragged
fn rotate_on_drag(drag: Trigger<Pointer<Drag>>, mut transforms: Query<&mut Transform>) { fn rotate_on_drag(drag: Trigger<Pointer<Drag>>, mut transforms: Query<&mut Transform>) {
let mut transform = transforms.get_mut(drag.entity()).unwrap(); let mut transform = transforms.get_mut(drag.target()).unwrap();
transform.rotate_y(drag.delta.x * 0.02); transform.rotate_y(drag.delta.x * 0.02);
transform.rotate_x(drag.delta.y * 0.02); transform.rotate_x(drag.delta.y * 0.02);
} }

View file

@ -28,13 +28,13 @@ fn setup_scene(
.observe(on_click_spawn_cube) .observe(on_click_spawn_cube)
.observe( .observe(
|out: Trigger<Pointer<Out>>, mut texts: Query<&mut TextColor>| { |out: Trigger<Pointer<Out>>, mut texts: Query<&mut TextColor>| {
let mut text_color = texts.get_mut(out.entity()).unwrap(); let mut text_color = texts.get_mut(out.target()).unwrap();
text_color.0 = Color::WHITE; text_color.0 = Color::WHITE;
}, },
) )
.observe( .observe(
|over: Trigger<Pointer<Over>>, mut texts: Query<&mut TextColor>| { |over: Trigger<Pointer<Over>>, mut texts: Query<&mut TextColor>| {
let mut color = texts.get_mut(over.entity()).unwrap(); let mut color = texts.get_mut(over.target()).unwrap();
color.0 = bevy::color::palettes::tailwind::CYAN_400.into(); color.0 = bevy::color::palettes::tailwind::CYAN_400.into();
}, },
); );
@ -81,7 +81,7 @@ fn on_click_spawn_cube(
} }
fn on_drag_rotate(drag: Trigger<Pointer<Drag>>, mut transforms: Query<&mut Transform>) { fn on_drag_rotate(drag: Trigger<Pointer<Drag>>, mut transforms: Query<&mut Transform>) {
if let Ok(mut transform) = transforms.get_mut(drag.entity()) { if let Ok(mut transform) = transforms.get_mut(drag.target()) {
transform.rotate_y(drag.delta.x * 0.02); transform.rotate_y(drag.delta.x * 0.02);
transform.rotate_x(drag.delta.y * 0.02); transform.rotate_x(drag.delta.y * 0.02);
} }

View file

@ -150,7 +150,7 @@ fn setup_atlas(
// An observer listener that changes the target entity's color. // An observer listener that changes the target entity's color.
fn recolor_on<E: Debug + Clone + Reflect>(color: Color) -> impl Fn(Trigger<E>, Query<&mut Sprite>) { fn recolor_on<E: Debug + Clone + Reflect>(color: Color) -> impl Fn(Trigger<E>, Query<&mut Sprite>) {
move |ev, mut sprites| { move |ev, mut sprites| {
let Ok(mut sprite) = sprites.get_mut(ev.entity()) else { let Ok(mut sprite) = sprites.get_mut(ev.target()) else {
return; return;
}; };
sprite.color = color; sprite.color = color;

View file

@ -284,7 +284,7 @@ mod animation {
animation: Res<Animation>, animation: Res<Animation>,
mut players: Query<(Entity, &mut AnimationPlayer)>, mut players: Query<(Entity, &mut AnimationPlayer)>,
) { ) {
let entity = children.get(trigger.entity()).unwrap()[0]; let entity = children.get(trigger.target()).unwrap()[0];
let entity = children.get(entity).unwrap()[0]; let entity = children.get(entity).unwrap()[0];
let (entity, mut player) = players.get_mut(entity).unwrap(); let (entity, mut player) = players.get_mut(entity).unwrap();

View file

@ -93,7 +93,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
mut commands: Commands mut commands: Commands
| { | {
if trigger.event().button == PointerButton::Primary { if trigger.event().button == PointerButton::Primary {
commands.entity(trigger.entity()).despawn_recursive(); commands.entity(trigger.target()).despawn_recursive();
} }
}); });
} }