bevy_ecs/observer/
entity_cloning.rs1use crate::{
4 component::ComponentCloneBehavior,
5 entity::{
6 CloneByFilter, ComponentCloneCtx, EntityClonerBuilder, EntityMapper, SourceComponent,
7 },
8 observer::ObservedBy,
9 world::World,
10};
11
12use super::Observer;
13
14impl<Filter: CloneByFilter> EntityClonerBuilder<'_, Filter> {
15 pub fn add_observers(&mut self, add_observers: bool) -> &mut Self {
17 if add_observers {
18 self.override_clone_behavior::<ObservedBy>(ComponentCloneBehavior::Custom(
19 component_clone_observed_by,
20 ))
21 } else {
22 self.remove_clone_behavior_override::<ObservedBy>()
23 }
24 }
25}
26
27fn component_clone_observed_by(_source: &SourceComponent, ctx: &mut ComponentCloneCtx) {
28 let target = ctx.target();
29 let source = ctx.source();
30
31 ctx.queue_deferred(move |world: &mut World, _mapper: &mut dyn EntityMapper| {
32 let observed_by = world
33 .get::<ObservedBy>(source)
34 .map(|observed_by| observed_by.0.clone())
35 .expect("Source entity must have ObservedBy");
36
37 world
38 .entity_mut(target)
39 .insert(ObservedBy(observed_by.clone()));
40
41 for observer_entity in observed_by.iter().copied() {
42 let mut observer_state = world
43 .get_mut::<Observer>(observer_entity)
44 .expect("Source observer entity must have Observer");
45 observer_state.descriptor.entities.push(target);
46 let event_keys = observer_state.descriptor.event_keys.clone();
47 let components = observer_state.descriptor.components.clone();
48 for event_key in event_keys {
49 let observers = world.observers.get_observers_mut(event_key);
50 if components.is_empty() {
51 if let Some(map) = observers.entity_observers.get(&source).cloned() {
52 observers.entity_observers.insert(target, map);
53 }
54 } else {
55 for component in &components {
56 let Some(observers) = observers.component_observers.get_mut(component)
57 else {
58 continue;
59 };
60 if let Some(map) =
61 observers.entity_component_observers.get(&source).cloned()
62 {
63 observers.entity_component_observers.insert(target, map);
64 }
65 }
66 }
67 }
68 }
69 });
70}
71
72#[cfg(test)]
73mod tests {
74 use crate::{
75 entity::{Entity, EntityCloner},
76 event::EntityEvent,
77 observer::On,
78 resource::Resource,
79 system::ResMut,
80 world::World,
81 };
82
83 #[derive(Resource, Default)]
84 struct Num(usize);
85
86 #[derive(EntityEvent)]
87 struct E(Entity);
88
89 #[test]
90 fn clone_entity_with_observer() {
91 let mut world = World::default();
92 world.init_resource::<Num>();
93
94 let e = world
95 .spawn_empty()
96 .observe(|_: On<E>, mut res: ResMut<Num>| res.0 += 1)
97 .id();
98 world.flush();
99
100 world.trigger(E(e));
101
102 let e_clone = world.spawn_empty().id();
103 EntityCloner::build_opt_out(&mut world)
104 .add_observers(true)
105 .clone_entity(e, e_clone);
106
107 world.trigger(E(e));
108 world.trigger(E(e_clone));
109
110 assert_eq!(world.resource::<Num>().0, 3);
111 }
112}