Path: blob/main/crates/bevy_ecs/src/observer/entity_cloning.rs
6604 views
//! Logic to track observers when cloning entities.12use crate::{3component::ComponentCloneBehavior,4entity::{5CloneByFilter, ComponentCloneCtx, EntityClonerBuilder, EntityMapper, SourceComponent,6},7observer::ObservedBy,8world::World,9};1011use super::Observer;1213impl<Filter: CloneByFilter> EntityClonerBuilder<'_, Filter> {14/// Sets the option to automatically add cloned entities to the observers targeting source entity.15pub fn add_observers(&mut self, add_observers: bool) -> &mut Self {16if add_observers {17self.override_clone_behavior::<ObservedBy>(ComponentCloneBehavior::Custom(18component_clone_observed_by,19))20} else {21self.remove_clone_behavior_override::<ObservedBy>()22}23}24}2526fn component_clone_observed_by(_source: &SourceComponent, ctx: &mut ComponentCloneCtx) {27let target = ctx.target();28let source = ctx.source();2930ctx.queue_deferred(move |world: &mut World, _mapper: &mut dyn EntityMapper| {31let observed_by = world32.get::<ObservedBy>(source)33.map(|observed_by| observed_by.0.clone())34.expect("Source entity must have ObservedBy");3536world37.entity_mut(target)38.insert(ObservedBy(observed_by.clone()));3940for observer_entity in observed_by.iter().copied() {41let mut observer_state = world42.get_mut::<Observer>(observer_entity)43.expect("Source observer entity must have Observer");44observer_state.descriptor.entities.push(target);45let event_keys = observer_state.descriptor.event_keys.clone();46let components = observer_state.descriptor.components.clone();47for event_key in event_keys {48let observers = world.observers.get_observers_mut(event_key);49if components.is_empty() {50if let Some(map) = observers.entity_observers.get(&source).cloned() {51observers.entity_observers.insert(target, map);52}53} else {54for component in &components {55let Some(observers) = observers.component_observers.get_mut(component)56else {57continue;58};59if let Some(map) =60observers.entity_component_observers.get(&source).cloned()61{62observers.entity_component_observers.insert(target, map);63}64}65}66}67}68});69}7071#[cfg(test)]72mod tests {73use crate::{74entity::{Entity, EntityCloner},75event::EntityEvent,76observer::On,77resource::Resource,78system::ResMut,79world::World,80};8182#[derive(Resource, Default)]83struct Num(usize);8485#[derive(EntityEvent)]86struct E(Entity);8788#[test]89fn clone_entity_with_observer() {90let mut world = World::default();91world.init_resource::<Num>();9293let e = world94.spawn_empty()95.observe(|_: On<E>, mut res: ResMut<Num>| res.0 += 1)96.id();97world.flush();9899world.trigger(E(e));100101let e_clone = world.spawn_empty().id();102EntityCloner::build_opt_out(&mut world)103.add_observers(true)104.clone_entity(e, e_clone);105106world.trigger(E(e));107world.trigger(E(e_clone));108109assert_eq!(world.resource::<Num>().0, 3);110}111}112113114