use crate::{IntoSendStorage, entity::EntitiesStorage, storage::FastIndexExt, sync::{StorageWriteGuard, OrderedIndexGuard}};
use std::marker;
use crate::Component;
use crate::ComponentSend;
use crate::Bitmask;
use super::{ChangesOrderedData, OrderedData, SafeIter};
use crate::storage::{StorageRef, HierarchicalStorage, IntoOrderedIterMut, IntoOrderedChangesIter};
use crate::utils::{delete_lifetime, delete_lifetime_mut};
use crate::idtree;
use std::ops::DerefMut;
use hashbrown::HashSet;
pub struct WriteAndParent<'a, T: Component>{
_marker: marker::PhantomData<&'a T>,
}
pub struct ParentStorageWrite<'a, S, BS, T>
where S: HierarchicalStorage<'a,T> + 'a,
BS: DerefMut<Target = S>,
T: Component
{
storage: BS,
_marker: marker::PhantomData<&'a T>,
}
impl<'a, S, BS, T> FastIndexExt for ParentStorageWrite<'a, S, BS, T>
where S: HierarchicalStorage<'a,T> + 'a,
BS: DerefMut<Target = S>,
T: Component
{
type FastIndex = idtree::NodeId;
type StaticTypeId = T;
fn fast_index(&self, guid: usize) -> idtree::NodeId {
unsafe{ self.storage.ordered_fast_index(guid) }
}
}
impl<'a, 'r, S, BS, T> StorageRef<'r> for ParentStorageWrite<'a, S, BS, T>
where S: HierarchicalStorage<'a,T> + 'a,
BS: DerefMut<Target = S>,
T: Component
{
type Component = (&'r mut T, Option<&'r T>);
type Data = WriteAndParent<'a, T>;
unsafe fn get_fast_unchecked(&'r mut self, idx: idtree::NodeId) -> Self::Component {
let mut node = self.storage.fast_get_node_mut(idx);
let parent = node.parent().map(|p| delete_lifetime(&p as &T));
let node = delete_lifetime_mut(&mut node as &mut T);
(node, parent)
}
unsafe fn get_unchecked(&'r mut self, guid: usize) -> Self::Component {
let mut node = self.storage.get_node_mut(guid);
let parent = node.parent().map(|p| delete_lifetime(&p as &T));
let node = delete_lifetime_mut(&mut node as &mut T);
(node, parent)
}
fn contains(&self, guid: usize) -> bool {
self.storage.contains(guid)
}
}
impl<'a, 'r, T> IntoSendStorage<'r> for ParentStorageWrite<'a, <T as Component>::Storage, StorageWriteGuard<'a, T>, T>
where
'a: 'r,
T: Component,
<T as Component>::Storage: HierarchicalStorage<'a,T> + 'a
{
type SendStorage = ParentStorageWrite<'a, <T as Component>::Storage, &'r mut <T as Component>::Storage, T>;
fn into_send_storage(&'r mut self) -> Self::SendStorage {
ParentStorageWrite {
storage: &mut self.storage,
_marker: marker::PhantomData,
}
}
}
pub struct WriteAndParentIter<'a, T: Component, I>
where for<'b> <T as Component>::Storage: HierarchicalStorage<'b,T>,
{
it: Option<I>,
marker: marker::PhantomData<&'a T>,
}
impl<'a,T,I> Iterator for WriteAndParentIter<'a, T, I>
where T: Component,
for<'b> <T as Component>::Storage: HierarchicalStorage<'b,T>,
I: Iterator<Item = idtree::NodeRefMut<'a, T>>,
{
type Item = (&'a mut T, Option<&'a T>);
fn next(&mut self) -> Option<(&'a mut T, Option<&'a T>)>{
self.it.as_mut().and_then(|it| it.next().map(|mut n| {
let n_ref = unsafe{ delete_lifetime_mut(&mut n as &mut T) };
let p = unsafe{ n.parent().map(|p| delete_lifetime(p as &T)) };
(n_ref, p)
}))
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.it.as_ref().map(|it| it.size_hint()).unwrap_or((0, None))
}
}
unsafe impl<T: Component> SafeIter<'_> for WriteAndParent<'_, T>{}
impl<'a, T: Component> OrderedData<'a> for WriteAndParent<'a,T>
where for<'b> <T as Component>::Storage: HierarchicalStorage<'b,T>,
for<'b> StorageWriteGuard<'b, T>: IntoOrderedIterMut
{
type Iter = WriteAndParentIter<'a, T, <StorageWriteGuard<'a, T> as IntoOrderedIterMut>::OrderedIterMut>;
type Components = T;
type ComponentsRef = (&'a mut T, Option<&'a T>);
type Storage = ParentStorageWrite<'a,
<T as Component>::Storage,
StorageWriteGuard<'a, T>,
Self::Components>;
fn query_mask<E: EntitiesStorage>(entities: &E) -> Bitmask{
Bitmask::has(entities.component_mask::<T>())
}
fn into_iter<E: EntitiesStorage>(entities: &'a E) -> Self::Iter{
WriteAndParentIter{
it: entities.storage_mut::<T>().map(|s| s.into_ordered_iter_mut()),
marker: marker::PhantomData
}
}
fn storage<E: EntitiesStorage>(entities: &'a E) -> Option<Self::Storage>{
Some(ParentStorageWrite{
storage: entities.storage_mut::<T>()?,
_marker: marker::PhantomData,
})
}
fn ordered_ids<S: FastIndexExt, E: EntitiesStorage>(entities: &'a E, query_mask: Bitmask, unordered_storage: &S) -> OrderedIndexGuard<'a>{
entities.ordered_entities_for::<T,S>(query_mask, unordered_storage)
}
}
impl<'a, T: ComponentSend> ChangesOrderedData<'a> for WriteAndParent<'a, T>
where for<'b> <T as Component>::Storage: HierarchicalStorage<'b,T>,
for<'b> StorageWriteGuard<'b, T>: IntoOrderedIterMut,
StorageWriteGuard<'a, T>: IntoOrderedChangesIter<'a, T, OrderedChangesItem = idtree::NodeRefMut<'a, T>>,
{
type SubStorage = ParentStorageWrite<'a,
<StorageWriteGuard<'a, T> as IntoOrderedChangesIter<'a, T>>::RawSubStorage,
<StorageWriteGuard<'a, T> as IntoOrderedChangesIter<'a, T>>::SubStorage,
Self::Components>;
fn extend_changes<F, E: EntitiesStorage>(entities: &'a E, mut f: F)
where F: FnMut(Self::ComponentsRef) -> bool
{
if let Some(storage) = entities.storage_mut::<T>() {
storage.ordered_extend_changes(|mut n| {
let n_ref = unsafe{ delete_lifetime_mut(&mut n as &mut T) };
let p = unsafe{ n.parent().map(|p| delete_lifetime(p as &T)) };
f((n_ref, p))
})
}
}
unsafe fn storage_and_changes<E: EntitiesStorage>(entities: &'a E) -> Option<(Self::SubStorage, &'a mut HashSet<usize>)>{
let (storage, changes) = entities.storage_mut::<T>()?
.into_storage_and_changes();
let storage = ParentStorageWrite {
storage,
_marker: marker::PhantomData,
};
Some((storage, changes))
}
}