diff options
| author | Sébastien Crozet <sebcrozet@dimforge.com> | 2024-03-17 21:20:18 +0100 |
|---|---|---|
| committer | Sébastien Crozet <sebcrozet@dimforge.com> | 2024-03-17 21:24:28 +0100 |
| commit | ecd308338b189ab569816a38a03e3f8b89669dde (patch) | |
| tree | fa612abff2f23ea6a5ff04c64c07296d9fb065c8 /src/data | |
| parent | da92e5c2837b27433286cf0dd9d887fd44dda254 (diff) | |
| download | rapier-bevy-glam.tar.gz rapier-bevy-glam.tar.bz2 rapier-bevy-glam.zip | |
feat: start experimenting with a glam/bevy versionbevy-glam
Diffstat (limited to 'src/data')
| -rw-r--r-- | src/data/arena.rs | 2 | ||||
| -rw-r--r-- | src/data/coarena.rs | 21 | ||||
| -rw-r--r-- | src/data/entity_arena.rs | 145 | ||||
| -rw-r--r-- | src/data/mod.rs | 6 |
4 files changed, 171 insertions, 3 deletions
diff --git a/src/data/arena.rs b/src/data/arena.rs index 57653da..3a8c613 100644 --- a/src/data/arena.rs +++ b/src/data/arena.rs @@ -76,7 +76,7 @@ impl Index { /// /// Providing arbitrary values will lead to malformed indices and ultimately /// panics. - pub fn from_raw_parts(index: u32, generation: u32) -> Index { + pub const fn from_raw_parts(index: u32, generation: u32) -> Index { Index { index, generation } } diff --git a/src/data/coarena.rs b/src/data/coarena.rs index 18fb055..2015b6f 100644 --- a/src/data/coarena.rs +++ b/src/data/coarena.rs @@ -1,12 +1,18 @@ use crate::data::arena::Index; #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] /// A container for data associated to item existing into another Arena. pub struct Coarena<T> { data: Vec<(u32, T)>, } +impl<T> Default for Coarena<T> { + fn default() -> Self { + Self { data: Vec::new() } + } +} + impl<T> Coarena<T> { /// A coarena with no element. pub fn new() -> Self { @@ -69,10 +75,21 @@ impl<T> Coarena<T> { where T: Clone + Default, { + self.insert_with_default(a, value, T::default()) + } + + /// Inserts an element into this coarena. + /// + /// The provided `default` value is used for any empty slots created + /// by this insertion. + pub fn insert_with_default(&mut self, a: Index, value: T, default: T) + where + T: Clone, + { let (i1, g1) = a.into_raw_parts(); if self.data.len() <= i1 as usize { - self.data.resize(i1 as usize + 1, (u32::MAX, T::default())); + self.data.resize(i1 as usize + 1, (u32::MAX, default)); } self.data[i1 as usize] = (g1, value); diff --git a/src/data/entity_arena.rs b/src/data/entity_arena.rs new file mode 100644 index 0000000..ad6e451 --- /dev/null +++ b/src/data/entity_arena.rs @@ -0,0 +1,145 @@ +use crate::data::arena::Index; +use crate::data::Arena; +use crate::data::Coarena; +use bevy::prelude::Entity; +use std::ops::IndexMut; + +impl From<Entity> for Index { + #[inline] + fn from(value: Entity) -> Self { + Index::from_raw_parts(value.index(), value.generation()) + } +} + +impl From<Index> for Entity { + #[inline] + fn from(value: Index) -> Self { + let (id, gen) = value.into_raw_parts(); + Entity::from_bits(id as u64 | ((gen as u64) << u32::BITS)) + } +} + +#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] +#[derive(Clone, Debug, Default)] +struct EntityMap { + entity_to_index: Coarena<Index>, + index_to_entity: Coarena<Entity>, // Is this really needed? +} + +impl EntityMap { + pub fn get_index(&self, entity: Entity) -> Option<Index> { + self.entity_to_index.get(entity.into()).copied() + } + + pub fn get_entity(&self, index: Index) -> Option<Entity> { + self.index_to_entity.get(index).copied() + } + + pub fn insert(&mut self, entity: Entity, index: Index) { + self.entity_to_index.insert(entity.into(), index); + self.index_to_entity + .insert_with_default(index, entity, Entity::PLACEHOLDER); + } + + pub fn remove(&mut self, entity: Entity) { + if let Some(index) = self.entity_to_index.remove( + entity.into(), + Index::from_raw_parts(crate::INVALID_U32, crate::INVALID_U32), + ) { + self.index_to_entity.remove(index, Entity::PLACEHOLDER); + } + } +} + +impl std::ops::Index<Index> for EntityMap { + type Output = Entity; + + fn index(&self, index: Index) -> &Self::Output { + self.index_to_entity.get(index).expect("Index not found.") + } +} + +impl std::ops::Index<Entity> for EntityMap { + type Output = Index; + + fn index(&self, entity: Entity) -> &Self::Output { + self.entity_to_index + .get(entity.into()) + .expect("Index not found.") + } +} + +#[derive(Clone, Debug)] +#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] +pub struct EntityArena<T> { + entity_map: EntityMap, + elements: Arena<T>, +} + +impl<T> Default for EntityArena<T> { + fn default() -> Self { + Self { + entity_map: EntityMap::default(), + elements: Arena::default(), + } + } +} + +impl<T> EntityArena<T> { + pub fn insert(&mut self, entity: Entity, value: T) { + let index = self.elements.insert(value); + self.entity_map.insert(entity, index); + } + + pub fn remove(&mut self, entity: Entity) -> Option<T> { + let elt = self.elements.remove(self.entity_map.get_index(entity)?)?; + self.entity_map.remove(entity); + Some(elt) + } + + pub fn contains(&self, entity: Entity) -> bool { + self.entity_map.get_index(entity).is_some() + } + + pub fn len(&self) -> usize { + self.elements.len() + } + + pub fn is_empty(&self) -> bool { + self.elements.is_empty() + } + + pub fn get(&self, entity: Entity) -> Option<&T> { + self.elements.get(self.entity_map.get_index(entity)?) + } + + pub fn get_mut(&mut self, entity: Entity) -> Option<&mut T> { + self.elements.get_mut(self.entity_map.get_index(entity)?) + } + + pub fn iter(&self) -> impl ExactSizeIterator<Item = (Entity, &T)> { + self.elements + .iter() + .map(|(h, data)| (self.entity_map[h], data)) + } + + pub fn iter_mut(&mut self) -> impl ExactSizeIterator<Item = (Entity, &mut T)> { + self.elements + .iter_mut() + .map(|(h, data)| (self.entity_map[h], data)) + } +} + +impl<T> std::ops::Index<Entity> for EntityArena<T> { + type Output = T; + + fn index(&self, index: Entity) -> &Self::Output { + &self.elements[self.entity_map[index]] + } +} + +impl<T> IndexMut<Entity> for EntityArena<T> { + fn index_mut(&mut self, index: Entity) -> &mut Self::Output { + &mut self.elements[self.entity_map[index]] + } +} diff --git a/src/data/mod.rs b/src/data/mod.rs index 6d9e2ce..c729202 100644 --- a/src/data/mod.rs +++ b/src/data/mod.rs @@ -3,7 +3,13 @@ pub use self::arena::{Arena, Index}; pub use self::coarena::Coarena; +#[cfg(feature = "bevy")] +pub use self::entity_arena::EntityArena; + pub mod arena; mod coarena; pub(crate) mod graph; pub mod pubsub; + +#[cfg(feature = "bevy")] +mod entity_arena; |
