use std::iter::Extend;
use std::ops::{Deref, DerefMut};
use shrev::{EventChannel, ReaderId};
use join::Join;
use storage::{MaskedStorage, Storage};
use world::{Component, Index};
pub trait Tracked {
fn channels(&self) -> &TrackChannels;
fn channels_mut(&mut self) -> &mut TrackChannels;
}
pub struct TrackChannels {
pub modify: EventChannel<ModifiedFlag>,
pub insert: EventChannel<InsertedFlag>,
pub remove: EventChannel<RemovedFlag>,
}
impl TrackChannels {
pub fn new() -> Self {
Default::default()
}
}
impl Default for TrackChannels {
fn default() -> Self {
TrackChannels {
modify: EventChannel::new(),
insert: EventChannel::new(),
remove: EventChannel::new(),
}
}
}
impl<'e, T, D> Storage<'e, T, D>
where
T: Component,
T::Storage: Tracked,
D: Deref<Target = MaskedStorage<T>>,
{
pub fn channels(&self) -> &TrackChannels {
self.open().1.channels()
}
pub fn modified(&self) -> &EventChannel<ModifiedFlag> {
&self.channels().modify
}
pub fn inserted(&self) -> &EventChannel<InsertedFlag> {
&self.channels().insert
}
pub fn removed(&self) -> &EventChannel<RemovedFlag> {
&self.channels().remove
}
pub fn populate_modified<E>(&self, reader_id: &mut ReaderId<ModifiedFlag>, value: &mut E)
where
E: Extend<Index>,
{
value.extend(self.modified().read(reader_id).map(|flag| *flag.as_ref()));
}
pub fn populate_inserted<E>(&self, reader_id: &mut ReaderId<InsertedFlag>, value: &mut E)
where
E: Extend<Index>,
{
value.extend(self.inserted().read(reader_id).map(|flag| *flag.as_ref()));
}
pub fn populate_removed<E>(&self, reader_id: &mut ReaderId<RemovedFlag>, value: &mut E)
where
E: Extend<Index>,
{
value.extend(self.removed().read(reader_id).map(|flag| *flag.as_ref()));
}
}
impl<'e, T, D> Storage<'e, T, D>
where
T: Component,
T::Storage: Tracked,
D: DerefMut<Target = MaskedStorage<T>>,
{
pub fn channels_mut(&mut self) -> &mut TrackChannels {
self.open().1.channels_mut()
}
pub fn modified_mut(&mut self) -> &mut EventChannel<ModifiedFlag> {
&mut self.channels_mut().modify
}
pub fn inserted_mut(&mut self) -> &mut EventChannel<InsertedFlag> {
&mut self.channels_mut().insert
}
pub fn removed_mut(&mut self) -> &mut EventChannel<RemovedFlag> {
&mut self.channels_mut().remove
}
pub fn track_modified(&mut self) -> ReaderId<ModifiedFlag> {
self.modified_mut().register_reader()
}
pub fn track_inserted(&mut self) -> ReaderId<InsertedFlag> {
self.inserted_mut().register_reader()
}
pub fn track_removed(&mut self) -> ReaderId<RemovedFlag> {
self.removed_mut().register_reader()
}
pub fn flag_modified(&mut self, id: Index) {
self.modified_mut().single_write(id.into());
}
pub fn flag_inserted(&mut self, id: Index) {
self.inserted_mut().single_write(id.into());
}
pub fn flag_removed(&mut self, id: Index) {
self.removed_mut().single_write(id.into());
}
}
macro_rules! flag {
( $( $name:ident ),* ) => {
$(
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct $name(Index);
impl Deref for $name {
type Target = Index;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl AsRef<Index> for $name {
fn as_ref(&self) -> &Index {
&self.0
}
}
impl From<Index> for $name {
fn from(flag: Index) -> Self {
$name(flag)
}
}
)*
}
}
flag!(ModifiedFlag, InsertedFlag, RemovedFlag);