Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_ecs/src/observer/entity_cloning.rs
6604 views
1
//! Logic to track observers when cloning entities.
2
3
use crate::{
4
component::ComponentCloneBehavior,
5
entity::{
6
CloneByFilter, ComponentCloneCtx, EntityClonerBuilder, EntityMapper, SourceComponent,
7
},
8
observer::ObservedBy,
9
world::World,
10
};
11
12
use super::Observer;
13
14
impl<Filter: CloneByFilter> EntityClonerBuilder<'_, Filter> {
15
/// Sets the option to automatically add cloned entities to the observers targeting source entity.
16
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
27
fn 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)]
73
mod 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
}
113
114