use crate::storage::{
Storage, HierarchicalStorage, OneToNStorage, IntoIter, IntoIterMut,
IntoOrderedIterMut, ChangedStorageExt, AutoChangedStorageExt, SliceView, SliceViewMut,
OrderedId
};
#[cfg(feature = "parallel_iter")]
use crate::storage::ParStorage;
use crate::sync::{ReadGuardRef, WriteGuardRef};
use crate::component::{Component, Changes, HasChanged};
use std::marker;
use crate::idtree;
use hashbrown::HashSet;
pub struct AutoChanged<S,T>{
storage: S,
changed: HashSet<usize>,
changed_might: HashSet<usize>,
all_might_change: bool,
storage_changed: bool,
_marker: marker::PhantomData<T>,
}
impl<'a,S,T> AutoChangedStorageExt<'a> for AutoChanged<S, T>
where S: Storage<'a,T>,
<S as Storage<'a,T>>::Get: HasChanged,
T: Component,
{
fn update_changed(&mut self){
if self.all_might_change {
self.changed.extend(self.storage.ided_iter()
.filter_map(|(id, c)| if c.changed() {
Some(id)
}else{
None
}));
self.all_might_change = false;
self.changed_might.clear();
}else if !self.changed_might.is_empty(){
let storage = &self.storage;
self.changed.extend(self.changed_might.drain()
.filter_map(|id| if unsafe{ storage.get(id).changed() }{
Some(id)
}else{
None
}))
}
}
}
impl<'a, S, T> ChangedStorageExt<'a> for AutoChanged<S,T>
where S: Storage<'a,T>,
<S as Storage<'a,T>>::Get: HasChanged,
T: Component,
{
fn changed_entities(&self) -> hashbrown::hash_set::Iter<usize>{
self.changed.iter()
}
}
impl<'a, T: 'a, S: Storage<'a,T>> Storage<'a, T> for AutoChanged<S,T>
where <S as Storage<'a,T>>::GetMut: Changes,
T: Component
{
type Get = <S as Storage<'a,T>>::Get;
type GetMut = <S as Storage<'a,T>>::GetMut;
type DerefTarget = <S as Storage<'a,T>>::DerefTarget;
type IdedIter = <S as Storage<'a,T>>::IdedIter;
type Iter = <S as Storage<'a,T>>::Iter;
type IterMut = <S as Storage<'a,T>>::IterMut;
#[inline]
fn new() -> AutoChanged<S,T>{
AutoChanged{
storage: S::new(),
changed: HashSet::new(),
changed_might: HashSet::new(),
all_might_change: false,
storage_changed: false,
_marker: marker::PhantomData
}
}
#[inline]
fn with_capacity(capacity: usize) -> Self{
AutoChanged{
storage: S::with_capacity(capacity),
changed: HashSet::with_capacity(capacity),
changed_might: HashSet::with_capacity(capacity),
all_might_change: false,
storage_changed: false,
_marker: marker::PhantomData
}
}
#[inline]
fn insert(&mut self, guid: usize, t: T){
self.storage_changed = true;
if !self.all_might_change {
self.changed_might.insert(guid);
}
self.storage.insert(guid, t);
}
#[inline]
fn remove(&mut self, guid: usize){
self.storage_changed = true;
self.changed.remove(&guid);
self.changed_might.remove(&guid);
self.storage.remove(guid);
}
#[inline]
unsafe fn get(&self, guid: usize) -> <S as Storage<'a,T>>::Get {
self.storage.get(guid)
}
#[inline]
unsafe fn get_mut(&mut self, guid: usize) -> <S as Storage<'a,T>>::GetMut {
if !self.all_might_change {
self.changed_might.insert(guid);
}
self.storage.get_mut(guid)
}
#[inline]
unsafe fn fast_get(&self, idx: usize) -> <S as Storage<'a,T>>::Get {
self.storage.fast_get(idx)
}
#[inline]
unsafe fn fast_get_mut(&mut self, idx: usize) -> <S as Storage<'a,T>>::GetMut {
if !self.all_might_change {
let guid = self.storage.guid_from_fast_index(idx);
self.changed_might.insert(guid);
}
self.storage.fast_get_mut(idx)
}
fn fast_index(&self, guid: usize) -> usize{
self.storage.fast_index(guid)
}
fn guid_from_fast_index(&self, idx: usize) -> usize{
self.storage.guid_from_fast_index(idx)
}
#[inline]
fn contains(&self, guid: usize) -> bool{
self.storage.contains(guid)
}
fn update(&mut self){
if !self.changed.is_empty() || (self.changed_might.is_empty() && !self.all_might_change) {
self.storage_changed = false;
}
if !self.changed.is_empty(){
for id in self.changed.drain(){
unsafe{ self.storage.get_mut(id).reset_changed() }
}
self.changed_might.clear();
self.all_might_change = false;
}
}
fn tracks_changes() -> bool { true }
fn storage_changed(&self) -> bool {
self.storage_changed || !self.changed.is_empty()
}
fn ided_iter(&self) -> Self::IdedIter{
self.storage.ided_iter()
}
fn iter(&self) -> Self::Iter{
self.storage.iter()
}
fn iter_mut(&mut self) -> Self::IterMut{
self.storage.iter_mut()
}
}
#[cfg(feature = "parallel_iter")]
impl<'a, T: 'a, S: ParStorage<'a,T>> ParStorage<'a, T> for AutoChanged<S,T>
where
S: Storage<'a, T>,
<S as Storage<'a,T>>::Get: Send,
<S as Storage<'a,T>>::GetMut: Changes + Send,
T: Component + Sync + Send
{
type ParIter = <S as ParStorage<'a,T>>::ParIter;
type ParIterMut = <S as ParStorage<'a,T>>::ParIterMut;
fn par_iter(&self) -> Self::ParIter{
self.storage.par_iter()
}
fn par_iter_mut(&mut self) -> Self::ParIterMut{
self.storage.par_iter_mut()
}
}
impl<'a, S, T> HierarchicalStorage<'a,T> for AutoChanged<S, T>
where S: HierarchicalStorage<'a,T>,
<S as Storage<'a,T>>::GetMut: Changes,
T: 'a + Component,
{
unsafe fn insert_child(&mut self, parent_guid: usize, guid: usize, value: T){
self.storage_changed = true;
self.storage.insert_child(parent_guid, guid, value)
}
unsafe fn get_node(&self, guid: usize) -> idtree::NodeRef<T>{
self.storage.get_node(guid)
}
unsafe fn get_node_mut(&mut self, guid: usize) -> idtree::NodeRefMut<T>{
if !self.all_might_change {
self.changed_might.insert(guid);
}
self.storage.get_node_mut(guid)
}
unsafe fn fast_get_node(&self, idx: idtree::NodeId) -> idtree::NodeRef<T>{
self.storage.fast_get_node(idx)
}
unsafe fn fast_get_node_mut(&mut self, idx: idtree::NodeId) -> idtree::NodeRefMut<T>{
self.storage.fast_get_node_mut(idx)
}
unsafe fn guid_for(&self, nodeid: idtree::NodeId) -> usize{
self.storage.guid_for(nodeid)
}
unsafe fn ordered_fast_index(&self, guid: usize) -> idtree::NodeId{
self.storage.ordered_fast_index(guid)
}
fn ordered_ids(&self) -> ReadGuardRef<Vec<OrderedId<idtree::NodeId>>> {
self.storage.ordered_ids()
}
}
impl<'a, S, T> OneToNStorage<'a,T> for AutoChanged<S, T>
where S: OneToNStorage<'a,T>,
<S as Storage<'a,T>>::GetMut: Changes,
T: 'a + Component,
{
fn insert_slice<I: IntoIterator<Item = T>>(&mut self, guid: usize, t: I){
self.storage_changed = true;
self.storage.insert_slice(guid, t)
}
unsafe fn get_slice(&self, guid: usize) -> SliceView<T>{
self.storage.get_slice(guid)
}
unsafe fn get_slice_mut(&mut self, guid: usize) -> SliceViewMut<T>{
self.storage.get_slice_mut(guid)
}
}
impl<'a, S, T> IntoIter for ReadGuardRef<'a, AutoChanged<S,T>>
where ReadGuardRef<'a,S>: IntoIter
{
type Iter = <ReadGuardRef<'a,S> as IntoIter>::Iter;
fn into_iter(self) -> <ReadGuardRef<'a,S> as IntoIter>::Iter{
ReadGuardRef::map(self, |changed| &changed.storage).into_iter()
}
}
impl<'a, S, T> IntoIterMut for WriteGuardRef<'a, AutoChanged<S,T>>
where WriteGuardRef<'a,S>: IntoIterMut
{
type IterMut = <WriteGuardRef<'a,S> as IntoIterMut>::IterMut;
fn into_iter_mut(mut self) -> <WriteGuardRef<'a,S> as IntoIterMut>::IterMut {
self.all_might_change = true;
WriteGuardRef::map(self, |changed| &mut changed.storage).into_iter_mut()
}
}
impl<'a, S, T> IntoOrderedIterMut for WriteGuardRef<'a, AutoChanged<S, T>>
where WriteGuardRef<'a, S>: IntoOrderedIterMut
{
type OrderedIterMut = <WriteGuardRef<'a, S> as IntoOrderedIterMut>::OrderedIterMut;
fn into_ordered_iter_mut(mut self) -> Self::OrderedIterMut {
self.all_might_change = true;
WriteGuardRef::map(self, |changed| &mut changed.storage).into_ordered_iter_mut()
}
}