specs/storage/flagged.rs
1use std::marker::PhantomData;
2
3use hibitset::BitSetLike;
4
5use crate::{
6 storage::{
7 ComponentEvent, DenseVecStorage, SharedGetMutStorage, SyncUnsafeCell, Tracked, TryDefault,
8 UnprotectedStorage,
9 },
10 world::{Component, Index},
11};
12
13use shrev::EventChannel;
14
15/// Wrapper storage that tracks modifications, insertions, and removals of
16/// components through an `EventChannel`.
17///
18/// **Note:** Joining over all components of a `FlaggedStorage`
19/// mutably will flag all components.
20///
21/// What you want to instead is to use `restrict_mut()` to first
22/// get the entities which contain the component and then conditionally
23/// modify the component after a call to `get_mut()` or `get_other_mut()`.
24///
25/// # Examples
26///
27/// ```
28/// extern crate specs;
29///
30/// use specs::prelude::*;
31///
32/// pub struct Comp(u32);
33/// impl Component for Comp {
34/// // `FlaggedStorage` acts as a wrapper around another storage.
35/// // You can put any store inside of here (e.g. HashMapStorage, VecStorage, etc.)
36/// //
37/// // It also works as `FlaggedStorage<Self>` and defaults to `DenseVecStorage<Self>`
38/// // for the inner storage.
39/// type Storage = FlaggedStorage<Self, VecStorage<Self>>;
40/// }
41///
42/// pub struct CompSystem {
43/// // These keep track of where you left off in the event channel.
44/// reader_id: ReaderId<ComponentEvent>,
45///
46/// // The bitsets you want to populate with modification/insertion events.
47/// modified: BitSet,
48/// inserted: BitSet,
49/// }
50///
51/// impl<'a> System<'a> for CompSystem {
52/// type SystemData = (Entities<'a>, WriteStorage<'a, Comp>);
53/// fn run(&mut self, (entities, mut comps): Self::SystemData) {
54/// // We want to clear the bitset first so we don't have left over events
55/// // from the last frame.
56/// //
57/// // However, if you want to accumulate changes over a couple frames then you
58/// // can only clear it when necessary. (This might be useful if you have some
59/// // sort of "tick" system in your game and only want to do operations every
60/// // 1/4th of a second or something)
61/// //
62/// // It is not okay to only read the events in an interval though as that could
63/// // leave behind events which would end up growing the event ring buffer to
64/// // extreme sizes.
65/// self.modified.clear();
66/// self.inserted.clear();
67///
68/// // Here we can populate the bitsets by iterating over the events.
69/// // You can also just iterate over the events without using a bitset which will
70/// // give you an ordered history of the events (which is good for caches and synchronizing
71/// // other storages, but this allows us to use them in joins with components.
72/// {
73/// let events = comps.channel()
74/// .read(&mut self.reader_id);
75/// for event in events {
76/// match event {
77/// ComponentEvent::Modified(id) => { self.modified.add(*id); },
78/// ComponentEvent::Inserted(id) => { self.inserted.add(*id); },
79/// _ => { },
80/// };
81/// }
82/// }
83///
84/// // Iterates over all components like normal.
85/// for comp in (&comps).join() {
86/// // ...
87/// }
88///
89/// // **Never do this**
90/// // This will flag all components as modified regardless of whether the inner loop
91/// // actually modified the component.
92/// //
93/// // Only do this if you have other filters, like some other components to filter
94/// // out the ones you want to modify.
95/// for comp in (&mut comps).join() {
96/// // ...
97/// }
98///
99/// // Instead you will want to restrict the amount of components iterated over, either through
100/// // other components in the join, or by using `RestrictedStorage` and only getting the component
101/// // mutably when you are sure you need to modify it.
102/// # let condition = true;
103/// for (entity, mut comps) in (&entities, &mut comps.restrict_mut()).join() {
104/// if condition { // check whether this component should be modified.
105/// let mut comp = comps.get_mut();
106/// // ...
107/// }
108/// }
109///
110/// // To iterate over the modified components:
111/// for comp in (&comps, &self.modified).join() {
112/// // ...
113/// }
114///
115/// // To iterate over all inserted/modified components;
116/// for comp in (&comps, &self.modified & &self.inserted).join() {
117/// // ...
118/// }
119/// }
120/// }
121///
122/// fn main() {
123/// let mut world = World::new();
124/// world.register::<Comp>();
125///
126/// // You will want to register the system `ReaderId`s
127/// // before adding/modifying/removing any entities and components.
128/// //
129/// // Otherwise you won't receive any of the modifications until
130/// // you start tracking them.
131/// let mut comp_system = {
132/// let mut comps = world.write_storage::<Comp>();
133/// CompSystem {
134/// reader_id: comps.register_reader(),
135/// modified: BitSet::new(),
136/// inserted: BitSet::new(),
137/// }
138/// };
139///
140/// world.create_entity().with(Comp(19u32)).build();
141///
142/// {
143/// let mut comps = world.write_storage::<Comp>();
144/// let events = comps.channel().read(&mut comp_system.reader_id);
145/// assert_eq!(events.len(), 1);
146/// }
147///
148/// #[cfg(feature = "storage-event-control")]
149/// {
150/// world.write_storage::<Comp>().set_event_emission(false);
151/// world.create_entity().with(Comp(19u32)).build();
152///
153/// {
154/// let mut comps = world.write_storage::<Comp>();
155/// let events = comps.channel().read(&mut comp_system.reader_id);
156/// assert_eq!(events.len(), 0);
157/// }
158///
159/// world.write_storage::<Comp>().set_event_emission(true);
160/// world.create_entity().with(Comp(19u32)).build();
161///
162/// {
163/// let mut comps = world.write_storage::<Comp>();
164/// let events = comps.channel().read(&mut comp_system.reader_id);
165/// assert_eq!(events.len(), 1);
166/// }
167/// }
168/// }
169/// ```
170pub struct FlaggedStorage<C, T = DenseVecStorage<C>> {
171 channel: SyncUnsafeCell<EventChannel<ComponentEvent>>,
172 storage: T,
173 #[cfg(feature = "storage-event-control")]
174 event_emission: bool,
175 phantom: PhantomData<C>,
176}
177
178impl<C, T> FlaggedStorage<C, T> {
179 #[cfg(feature = "storage-event-control")]
180 fn emit_event(&self) -> bool {
181 self.event_emission
182 }
183
184 #[cfg(not(feature = "storage-event-control"))]
185 fn emit_event(&self) -> bool {
186 true
187 }
188}
189
190impl<C, T> Default for FlaggedStorage<C, T>
191where
192 T: TryDefault,
193{
194 fn default() -> Self {
195 FlaggedStorage {
196 channel: SyncUnsafeCell::new(EventChannel::<ComponentEvent>::default()),
197 storage: T::unwrap_default(),
198 #[cfg(feature = "storage-event-control")]
199 event_emission: true,
200 phantom: PhantomData,
201 }
202 }
203}
204
205impl<C: Component, T: UnprotectedStorage<C>> UnprotectedStorage<C> for FlaggedStorage<C, T> {
206 type AccessMut<'a> = <T as UnprotectedStorage<C>>::AccessMut<'a> where T: 'a;
207
208 unsafe fn clean<B>(&mut self, has: B)
209 where
210 B: BitSetLike,
211 {
212 // SAFETY: Requirements passed to caller.
213 unsafe { self.storage.clean(has) };
214 }
215
216 unsafe fn get(&self, id: Index) -> &C {
217 // SAFETY: Requirements passed to caller.
218 unsafe { self.storage.get(id) }
219 }
220
221 unsafe fn get_mut(&mut self, id: Index) -> <T as UnprotectedStorage<C>>::AccessMut<'_> {
222 if self.emit_event() {
223 self.channel
224 .get_mut()
225 .single_write(ComponentEvent::Modified(id));
226 }
227 // SAFETY: Requirements passed to caller.
228 unsafe { self.storage.get_mut(id) }
229 }
230
231 unsafe fn insert(&mut self, id: Index, comp: C) {
232 if self.emit_event() {
233 self.channel
234 .get_mut()
235 .single_write(ComponentEvent::Inserted(id));
236 }
237 // SAFETY: Requirements passed to caller.
238 unsafe { self.storage.insert(id, comp) };
239 }
240
241 unsafe fn remove(&mut self, id: Index) -> C {
242 if self.emit_event() {
243 self.channel
244 .get_mut()
245 .single_write(ComponentEvent::Removed(id));
246 }
247 // SAFETY: Requirements passed to caller.
248 unsafe { self.storage.remove(id) }
249 }
250}
251
252impl<C: Component, T: SharedGetMutStorage<C>> SharedGetMutStorage<C> for FlaggedStorage<C, T> {
253 unsafe fn shared_get_mut(&self, id: Index) -> <T as UnprotectedStorage<C>>::AccessMut<'_> {
254 if self.emit_event() {
255 let channel_ptr = self.channel.get();
256 // SAFETY: Caller required to ensure references returned from other
257 // safe methods such as Tracked::channel are no longer alive. This
258 // storage is not marked with a `DistinctStorage` impl.
259 unsafe { &mut *channel_ptr }.single_write(ComponentEvent::Modified(id));
260 }
261 // SAFETY: Requirements passed to caller.
262 unsafe { self.storage.shared_get_mut(id) }
263 }
264}
265
266impl<C, T> Tracked for FlaggedStorage<C, T> {
267 fn channel(&self) -> &EventChannel<ComponentEvent> {
268 let channel_ptr = self.channel.get();
269 // SAFETY: The only place that mutably accesses the channel via a shared
270 // reference is the impl of `SharedGetMut::shared_get_mut` which
271 // requires callers to avoid calling other methods with `&self` while
272 // references returned there are still in use (and to ensure references
273 // from methods like this no longer exist).
274 unsafe { &*channel_ptr }
275 }
276
277 fn channel_mut(&mut self) -> &mut EventChannel<ComponentEvent> {
278 self.channel.get_mut()
279 }
280
281 #[cfg(feature = "storage-event-control")]
282 fn set_event_emission(&mut self, emit: bool) {
283 self.event_emission = emit;
284 }
285
286 #[cfg(feature = "storage-event-control")]
287 fn event_emission(&self) -> bool {
288 self.event_emission
289 }
290}