1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
use std::ops::{Deref, DerefMut};

use shrev::{EventChannel, ReaderId};

use crate::{
    join::Join,
    storage::{MaskedStorage, Storage},
    world::{Component, Index},
};

/// `UnprotectedStorage`s that track modifications, insertions, and
/// removals of components.
pub trait Tracked {
    /// Event channel tracking modified/inserted/removed components.
    fn channel(&self) -> &EventChannel<ComponentEvent>;
    /// Mutable event channel tracking modified/inserted/removed components.
    fn channel_mut(&mut self) -> &mut EventChannel<ComponentEvent>;

    /// Controls the events signal emission.
    /// When this is set to false the events modified/inserted/removed are
    /// not emitted.
    #[cfg(feature = "storage-event-control")]
    fn set_event_emission(&mut self, emit: bool);

    /// Returns the actual state of the event emission.
    #[cfg(feature = "storage-event-control")]
    fn event_emission(&self) -> bool;
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
/// Component storage events received from a `FlaggedStorage` or any storage
/// that implements `Tracked`.
pub enum ComponentEvent {
    /// An insertion event, note that a modification event will be triggered if
    /// the entity already had a component and had a new one inserted.
    Inserted(Index),
    /// A modification event, this will be sent any time a component is accessed
    /// mutably so be careful with joins over `&mut storages` as it could
    /// potentially flag all of them.
    Modified(Index),
    /// A removal event.
    Removed(Index),
}

impl<'e, T, D> Storage<'e, T, D>
where
    T: Component,
    T::Storage: Tracked,
    D: Deref<Target = MaskedStorage<T>>,
{
    /// Returns the event channel tracking modified components.
    pub fn channel(&self) -> &EventChannel<ComponentEvent> {
        unsafe { self.open() }.1.channel()
    }

    /// Returns the actual state of the event emission.
    #[cfg(feature = "storage-event-control")]
    pub fn event_emission(&self) -> bool {
        unsafe { self.open() }.1.event_emission()
    }
}

impl<'e, T, D> Storage<'e, T, D>
where
    T: Component,
    T::Storage: Tracked,
    D: DerefMut<Target = MaskedStorage<T>>,
{
    /// Returns the event channel for insertions/removals/modifications of this
    /// storage's components.
    pub fn channel_mut(&mut self) -> &mut EventChannel<ComponentEvent> {
        unsafe { self.open() }.1.channel_mut()
    }

    /// Starts tracking component events. Note that this reader id should be
    /// used every frame, otherwise events will pile up and memory use by
    /// the event channel will grow waiting for this reader.
    pub fn register_reader(&mut self) -> ReaderId<ComponentEvent> {
        self.channel_mut().register_reader()
    }

    /// Flags an index with a `ComponentEvent`.
    pub fn flag(&mut self, event: ComponentEvent) {
        self.channel_mut().single_write(event);
    }

    /// Controls the events signal emission.
    /// When this is set to false the events modified/inserted/removed are
    /// not emitted.
    #[cfg(feature = "storage-event-control")]
    pub fn set_event_emission(&mut self, emit: bool) {
        unsafe { self.open() }.1.set_event_emission(emit);
    }
}