Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_ecs/src/observer/centralized_storage.rs
6849 views
1
//! Centralized storage for observers, allowing for efficient look-ups.
2
//!
3
//! This has multiple levels:
4
//! - [`World::observers`](crate::world::World::observers) provides access to [`Observers`], which is a central storage for all observers.
5
//! - [`Observers`] contains multiple distinct caches in the form of [`CachedObservers`].
6
//! - Most observers are looked up by the [`ComponentId`] of the event they are observing
7
//! - Lifecycle observers have their own fields to save lookups.
8
//! - [`CachedObservers`] contains maps of [`ObserverRunner`]s, which are the actual functions that will be run when the observer is triggered.
9
//! - These are split by target type, in order to allow for different lookup strategies.
10
//! - [`CachedComponentObservers`] is one of these maps, which contains observers that are specifically targeted at a component.
11
12
use bevy_platform::collections::HashMap;
13
14
use crate::{
15
archetype::ArchetypeFlags, component::ComponentId, entity::EntityHashMap, event::EventKey,
16
observer::ObserverRunner,
17
};
18
19
/// An internal lookup table tracking all of the observers in the world.
20
///
21
/// Stores a cache mapping event ids to their registered observers.
22
/// Some observer kinds (like [lifecycle](crate::lifecycle) observers) have a dedicated field,
23
/// saving lookups for the most common triggers.
24
///
25
/// This can be accessed via [`World::observers`](crate::world::World::observers).
26
#[derive(Default, Debug)]
27
pub struct Observers {
28
// Cached ECS observers to save a lookup for high-traffic built-in event types.
29
add: CachedObservers,
30
insert: CachedObservers,
31
replace: CachedObservers,
32
remove: CachedObservers,
33
despawn: CachedObservers,
34
// Map from event type to set of observers watching for that event
35
cache: HashMap<EventKey, CachedObservers>,
36
}
37
38
impl Observers {
39
pub(crate) fn get_observers_mut(&mut self, event_key: EventKey) -> &mut CachedObservers {
40
use crate::lifecycle::*;
41
42
match event_key {
43
ADD => &mut self.add,
44
INSERT => &mut self.insert,
45
REPLACE => &mut self.replace,
46
REMOVE => &mut self.remove,
47
DESPAWN => &mut self.despawn,
48
_ => self.cache.entry(event_key).or_default(),
49
}
50
}
51
52
/// Attempts to get the observers for the given `event_key`.
53
///
54
/// When accessing the observers for lifecycle events, such as [`Add`], [`Insert`], [`Replace`], [`Remove`], and [`Despawn`],
55
/// use the [`EventKey`] constants from the [`lifecycle`](crate::lifecycle) module.
56
///
57
/// [`Add`]: crate::lifecycle::Add
58
/// [`Insert`]: crate::lifecycle::Insert
59
/// [`Replace`]: crate::lifecycle::Replace
60
/// [`Remove`]: crate::lifecycle::Remove
61
/// [`Despawn`]: crate::lifecycle::Despawn
62
pub fn try_get_observers(&self, event_key: EventKey) -> Option<&CachedObservers> {
63
use crate::lifecycle::*;
64
65
match event_key {
66
ADD => Some(&self.add),
67
INSERT => Some(&self.insert),
68
REPLACE => Some(&self.replace),
69
REMOVE => Some(&self.remove),
70
DESPAWN => Some(&self.despawn),
71
_ => self.cache.get(&event_key),
72
}
73
}
74
75
pub(crate) fn is_archetype_cached(event_key: EventKey) -> Option<ArchetypeFlags> {
76
use crate::lifecycle::*;
77
78
match event_key {
79
ADD => Some(ArchetypeFlags::ON_ADD_OBSERVER),
80
INSERT => Some(ArchetypeFlags::ON_INSERT_OBSERVER),
81
REPLACE => Some(ArchetypeFlags::ON_REPLACE_OBSERVER),
82
REMOVE => Some(ArchetypeFlags::ON_REMOVE_OBSERVER),
83
DESPAWN => Some(ArchetypeFlags::ON_DESPAWN_OBSERVER),
84
_ => None,
85
}
86
}
87
88
pub(crate) fn update_archetype_flags(
89
&self,
90
component_id: ComponentId,
91
flags: &mut ArchetypeFlags,
92
) {
93
if self.add.component_observers.contains_key(&component_id) {
94
flags.insert(ArchetypeFlags::ON_ADD_OBSERVER);
95
}
96
97
if self.insert.component_observers.contains_key(&component_id) {
98
flags.insert(ArchetypeFlags::ON_INSERT_OBSERVER);
99
}
100
101
if self.replace.component_observers.contains_key(&component_id) {
102
flags.insert(ArchetypeFlags::ON_REPLACE_OBSERVER);
103
}
104
105
if self.remove.component_observers.contains_key(&component_id) {
106
flags.insert(ArchetypeFlags::ON_REMOVE_OBSERVER);
107
}
108
109
if self.despawn.component_observers.contains_key(&component_id) {
110
flags.insert(ArchetypeFlags::ON_DESPAWN_OBSERVER);
111
}
112
}
113
}
114
115
/// Collection of [`ObserverRunner`] for [`Observer`](crate::observer::Observer) registered to a particular event.
116
///
117
/// This is stored inside of [`Observers`], specialized for each kind of observer.
118
#[derive(Default, Debug)]
119
pub struct CachedObservers {
120
/// Observers watching for any time this event is triggered, regardless of target.
121
/// These will also respond to events targeting specific components or entities
122
pub(super) global_observers: ObserverMap,
123
/// Observers watching for triggers of events for a specific component
124
pub(super) component_observers: HashMap<ComponentId, CachedComponentObservers>,
125
/// Observers watching for triggers of events for a specific entity
126
pub(super) entity_observers: EntityHashMap<ObserverMap>,
127
}
128
129
impl CachedObservers {
130
/// Observers watching for any time this event is triggered, regardless of target.
131
/// These will also respond to events targeting specific components or entities
132
pub fn global_observers(&self) -> &ObserverMap {
133
&self.global_observers
134
}
135
136
/// Returns observers watching for triggers of events for a specific component.
137
pub fn component_observers(&self) -> &HashMap<ComponentId, CachedComponentObservers> {
138
&self.component_observers
139
}
140
141
/// Returns observers watching for triggers of events for a specific entity.
142
pub fn entity_observers(&self) -> &EntityHashMap<ObserverMap> {
143
&self.entity_observers
144
}
145
}
146
147
/// Map between an observer entity and its [`ObserverRunner`]
148
pub type ObserverMap = EntityHashMap<ObserverRunner>;
149
150
/// Collection of [`ObserverRunner`] for [`Observer`](crate::observer::Observer) registered to a particular event targeted at a specific component.
151
///
152
/// This is stored inside of [`CachedObservers`].
153
#[derive(Default, Debug)]
154
pub struct CachedComponentObservers {
155
// Observers watching for events targeting this component, but not a specific entity
156
pub(super) global_observers: ObserverMap,
157
// Observers watching for events targeting this component on a specific entity
158
pub(super) entity_component_observers: EntityHashMap<ObserverMap>,
159
}
160
161
impl CachedComponentObservers {
162
/// Returns observers watching for events targeting this component, but not a specific entity
163
pub fn global_observers(&self) -> &ObserverMap {
164
&self.global_observers
165
}
166
167
/// Returns observers watching for events targeting this component on a specific entity
168
pub fn entity_component_observers(&self) -> &EntityHashMap<ObserverMap> {
169
&self.entity_component_observers
170
}
171
}
172
173