Path: blob/main/crates/bevy_ecs/src/observer/centralized_storage.rs
6849 views
//! Centralized storage for observers, allowing for efficient look-ups.1//!2//! This has multiple levels:3//! - [`World::observers`](crate::world::World::observers) provides access to [`Observers`], which is a central storage for all observers.4//! - [`Observers`] contains multiple distinct caches in the form of [`CachedObservers`].5//! - Most observers are looked up by the [`ComponentId`] of the event they are observing6//! - Lifecycle observers have their own fields to save lookups.7//! - [`CachedObservers`] contains maps of [`ObserverRunner`]s, which are the actual functions that will be run when the observer is triggered.8//! - These are split by target type, in order to allow for different lookup strategies.9//! - [`CachedComponentObservers`] is one of these maps, which contains observers that are specifically targeted at a component.1011use bevy_platform::collections::HashMap;1213use crate::{14archetype::ArchetypeFlags, component::ComponentId, entity::EntityHashMap, event::EventKey,15observer::ObserverRunner,16};1718/// An internal lookup table tracking all of the observers in the world.19///20/// Stores a cache mapping event ids to their registered observers.21/// Some observer kinds (like [lifecycle](crate::lifecycle) observers) have a dedicated field,22/// saving lookups for the most common triggers.23///24/// This can be accessed via [`World::observers`](crate::world::World::observers).25#[derive(Default, Debug)]26pub struct Observers {27// Cached ECS observers to save a lookup for high-traffic built-in event types.28add: CachedObservers,29insert: CachedObservers,30replace: CachedObservers,31remove: CachedObservers,32despawn: CachedObservers,33// Map from event type to set of observers watching for that event34cache: HashMap<EventKey, CachedObservers>,35}3637impl Observers {38pub(crate) fn get_observers_mut(&mut self, event_key: EventKey) -> &mut CachedObservers {39use crate::lifecycle::*;4041match event_key {42ADD => &mut self.add,43INSERT => &mut self.insert,44REPLACE => &mut self.replace,45REMOVE => &mut self.remove,46DESPAWN => &mut self.despawn,47_ => self.cache.entry(event_key).or_default(),48}49}5051/// Attempts to get the observers for the given `event_key`.52///53/// When accessing the observers for lifecycle events, such as [`Add`], [`Insert`], [`Replace`], [`Remove`], and [`Despawn`],54/// use the [`EventKey`] constants from the [`lifecycle`](crate::lifecycle) module.55///56/// [`Add`]: crate::lifecycle::Add57/// [`Insert`]: crate::lifecycle::Insert58/// [`Replace`]: crate::lifecycle::Replace59/// [`Remove`]: crate::lifecycle::Remove60/// [`Despawn`]: crate::lifecycle::Despawn61pub fn try_get_observers(&self, event_key: EventKey) -> Option<&CachedObservers> {62use crate::lifecycle::*;6364match event_key {65ADD => Some(&self.add),66INSERT => Some(&self.insert),67REPLACE => Some(&self.replace),68REMOVE => Some(&self.remove),69DESPAWN => Some(&self.despawn),70_ => self.cache.get(&event_key),71}72}7374pub(crate) fn is_archetype_cached(event_key: EventKey) -> Option<ArchetypeFlags> {75use crate::lifecycle::*;7677match event_key {78ADD => Some(ArchetypeFlags::ON_ADD_OBSERVER),79INSERT => Some(ArchetypeFlags::ON_INSERT_OBSERVER),80REPLACE => Some(ArchetypeFlags::ON_REPLACE_OBSERVER),81REMOVE => Some(ArchetypeFlags::ON_REMOVE_OBSERVER),82DESPAWN => Some(ArchetypeFlags::ON_DESPAWN_OBSERVER),83_ => None,84}85}8687pub(crate) fn update_archetype_flags(88&self,89component_id: ComponentId,90flags: &mut ArchetypeFlags,91) {92if self.add.component_observers.contains_key(&component_id) {93flags.insert(ArchetypeFlags::ON_ADD_OBSERVER);94}9596if self.insert.component_observers.contains_key(&component_id) {97flags.insert(ArchetypeFlags::ON_INSERT_OBSERVER);98}99100if self.replace.component_observers.contains_key(&component_id) {101flags.insert(ArchetypeFlags::ON_REPLACE_OBSERVER);102}103104if self.remove.component_observers.contains_key(&component_id) {105flags.insert(ArchetypeFlags::ON_REMOVE_OBSERVER);106}107108if self.despawn.component_observers.contains_key(&component_id) {109flags.insert(ArchetypeFlags::ON_DESPAWN_OBSERVER);110}111}112}113114/// Collection of [`ObserverRunner`] for [`Observer`](crate::observer::Observer) registered to a particular event.115///116/// This is stored inside of [`Observers`], specialized for each kind of observer.117#[derive(Default, Debug)]118pub struct CachedObservers {119/// Observers watching for any time this event is triggered, regardless of target.120/// These will also respond to events targeting specific components or entities121pub(super) global_observers: ObserverMap,122/// Observers watching for triggers of events for a specific component123pub(super) component_observers: HashMap<ComponentId, CachedComponentObservers>,124/// Observers watching for triggers of events for a specific entity125pub(super) entity_observers: EntityHashMap<ObserverMap>,126}127128impl CachedObservers {129/// Observers watching for any time this event is triggered, regardless of target.130/// These will also respond to events targeting specific components or entities131pub fn global_observers(&self) -> &ObserverMap {132&self.global_observers133}134135/// Returns observers watching for triggers of events for a specific component.136pub fn component_observers(&self) -> &HashMap<ComponentId, CachedComponentObservers> {137&self.component_observers138}139140/// Returns observers watching for triggers of events for a specific entity.141pub fn entity_observers(&self) -> &EntityHashMap<ObserverMap> {142&self.entity_observers143}144}145146/// Map between an observer entity and its [`ObserverRunner`]147pub type ObserverMap = EntityHashMap<ObserverRunner>;148149/// Collection of [`ObserverRunner`] for [`Observer`](crate::observer::Observer) registered to a particular event targeted at a specific component.150///151/// This is stored inside of [`CachedObservers`].152#[derive(Default, Debug)]153pub struct CachedComponentObservers {154// Observers watching for events targeting this component, but not a specific entity155pub(super) global_observers: ObserverMap,156// Observers watching for events targeting this component on a specific entity157pub(super) entity_component_observers: EntityHashMap<ObserverMap>,158}159160impl CachedComponentObservers {161/// Returns observers watching for events targeting this component, but not a specific entity162pub fn global_observers(&self) -> &ObserverMap {163&self.global_observers164}165166/// Returns observers watching for events targeting this component on a specific entity167pub fn entity_component_observers(&self) -> &EntityHashMap<ObserverMap> {168&self.entity_component_observers169}170}171172173