bevy/crates/bevy_ecs/src/observer/entity_observer.rs
Martín Maita eca8220761
Generalised ECS reactivity with Observers (#10839) (#13873)
# Objective

- Fixes #13825 

## Solution

- Cherry picked and fixed non-trivial conflicts to be able to merge
#10839 into the 0.14 release branch.

Link to PR: https://github.com/bevyengine/bevy/pull/10839

Co-authored-by: James O'Brien <james.obrien@drafly.net>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: MiniaczQ <xnetroidpl@gmail.com>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2024-06-16 11:44:08 -04:00

43 lines
1.5 KiB
Rust

use crate::{
component::{Component, ComponentHooks, StorageType},
entity::Entity,
observer::ObserverState,
};
/// Tracks a list of entity observers for the [`Entity`] [`ObservedBy`] is added to.
#[derive(Default)]
pub(crate) struct ObservedBy(pub(crate) Vec<Entity>);
impl Component for ObservedBy {
const STORAGE_TYPE: StorageType = StorageType::SparseSet;
fn register_component_hooks(hooks: &mut ComponentHooks) {
hooks.on_remove(|mut world, entity, _| {
let observed_by = {
let mut component = world.get_mut::<ObservedBy>(entity).unwrap();
std::mem::take(&mut component.0)
};
for e in observed_by {
let (total_entities, despawned_watched_entities) = {
let Some(mut entity_mut) = world.get_entity_mut(e) else {
continue;
};
let Some(mut state) = entity_mut.get_mut::<ObserverState>() else {
continue;
};
state.despawned_watched_entities += 1;
(
state.descriptor.entities.len(),
state.despawned_watched_entities as usize,
)
};
// Despawn Observer if it has no more active sources.
if total_entities == despawned_watched_entities {
world.commands().entity(e).despawn();
}
}
});
}
}