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}