specs_mirror/
lib.rs

1#![deny(missing_docs)]
2//! This crate provides [`MirroredStorage`], an implementation of a [`specs`] storage
3//! that can track additions, removals and changes to the component it contains.
4//!
5//! [`MirroredStorage`]: struct.MirroredStorage.html
6//! [`specs`]: https://crates.io/crates/specs
7
8extern crate hibitset;
9extern crate shrev;
10extern crate specs;
11
12use hibitset::BitSetLike;
13use shrev::{EventChannel, EventIterator};
14use specs::prelude::*;
15use specs::storage::{MaskedStorage, TryDefault, UnprotectedStorage};
16use specs::world::Index;
17
18use std::any::Any;
19use std::ops::{Deref, DerefMut};
20
21/// A [`specs`] storage intended for synchronisation with external libraries.
22///
23/// [`specs`]: https://crates.io/crates/specs
24pub struct MirroredStorage<C: Mirrored, S = DenseVecStorage<C>> {
25    chan: EventChannel<C::Event>,
26    store: S,
27}
28
29/// Components that can be tracked in a [`MirroredStorage`].
30///
31/// [`MirroredStorage`]: struct.MirroredStorage.html
32pub trait Mirrored {
33    /// The event type for reporting changes to this component.
34    type Event: shrev::Event;
35
36    /// Called when inserting the component.
37    /// This method should not be called directly.
38    fn insert(&mut self, _chan: &mut EventChannel<Self::Event>, _id: Index) {}
39
40    /// Called when removing the component.
41    /// This method should not be called directly.
42    fn remove(&mut self, _chan: &mut EventChannel<Self::Event>, _id: Index) {}
43}
44
45impl<C: Mirrored, S: UnprotectedStorage<C>> MirroredStorage<C, S> {
46    /// Modify the component at the given index.
47    unsafe fn modify(&mut self, id: Index) -> (&mut C, &mut EventChannel<C::Event>) {
48        (self.store.get_mut(id), &mut self.chan)
49    }
50}
51
52impl<C: Mirrored, S> Default for MirroredStorage<C, S>
53where
54    S: TryDefault,
55{
56    fn default() -> Self {
57        MirroredStorage {
58            chan: EventChannel::new(),
59            store: S::unwrap_default(),
60        }
61    }
62}
63
64impl<C, S> UnprotectedStorage<C> for MirroredStorage<C, S>
65where
66    C: Mirrored + Component,
67    S: UnprotectedStorage<C>,
68{
69    unsafe fn clean<B>(&mut self, has: B)
70    where
71        B: BitSetLike,
72    {
73        self.store.clean(has)
74    }
75
76    unsafe fn get(&self, id: Index) -> &C {
77        self.store.get(id)
78    }
79
80    unsafe fn get_mut(&mut self, id: Index) -> &mut C {
81        self.store.get_mut(id)
82    }
83
84    unsafe fn insert(&mut self, id: Index, mut comp: C) {
85        comp.insert(&mut self.chan, id);
86        self.store.insert(id, comp);
87    }
88
89    unsafe fn remove(&mut self, id: Index) -> C {
90        let mut comp = self.store.remove(id);
91        comp.remove(&mut self.chan, id);
92        comp
93    }
94}
95
96/// Extension methods for [`Storage`] to help read events from [`MirroredStorage`].
97///
98/// [`MirroredStorage`]: struct.MirroredStorage.html
99/// [`Storage`]: https://docs.rs/specs/0.11.2/specs/storage/struct.Storage.html
100pub trait StorageExt<C: Mirrored> {
101    /// Read insertion and removal events from the event channel.
102    fn read_events(&self, reader: &mut ReaderId<C::Event>) -> EventIterator<C::Event>;
103}
104
105/// Extension methods for [`Storage`] to help read events from [`MirroredStorage`].
106///
107/// [`MirroredStorage`]: struct.MirroredStorage.html
108/// [`Storage`]: https://docs.rs/specs/0.11.2/specs/storage/struct.Storage.html
109pub trait StorageMutExt<C: Mirrored>: StorageExt<C> {
110    /// Register a new reader of insertion and removal events.
111    fn register_reader(&mut self) -> ReaderId<C::Event> {
112        self.event_channel().register_reader()
113    }
114
115    /// Get a mutable reference to the component and the event channel for update events.
116    fn modify(&mut self, entity: Entity) -> Option<(&mut C, &mut EventChannel<C::Event>)>;
117
118    /// Get a mutable reference to the event channel for update events.
119    fn event_channel(&mut self) -> &mut EventChannel<C::Event>;
120}
121
122impl<'a, C, S, D> StorageExt<C> for Storage<'a, C, D>
123where
124    C: Mirrored + Component<Storage = MirroredStorage<C, S>>,
125    S: UnprotectedStorage<C> + Any + Send + Sync,
126    D: Deref<Target = MaskedStorage<C>>,
127{
128    fn read_events(&self, reader: &mut ReaderId<C::Event>) -> EventIterator<C::Event> {
129        self.unprotected_storage().chan.read(reader)
130    }
131}
132
133impl<'a, C, S, D> StorageMutExt<C> for Storage<'a, C, D>
134where
135    C: Mirrored + Component<Storage = MirroredStorage<C, S>>,
136    S: UnprotectedStorage<C> + Any + Send + Sync,
137    D: DerefMut<Target = MaskedStorage<C>>,
138{
139    fn modify(&mut self, entity: Entity) -> Option<(&mut C, &mut EventChannel<C::Event>)> {
140        if self.contains(entity) {
141            Some(unsafe { self.unprotected_storage_mut().modify(entity.id()) })
142        } else {
143            None
144        }
145    }
146
147    fn event_channel(&mut self) -> &mut EventChannel<C::Event> {
148        unsafe { &mut self.unprotected_storage_mut().chan }
149    }
150}