aboutsummaryrefslogtreecommitdiff
path: root/src/data
diff options
context:
space:
mode:
authorSébastien Crozet <sebcrozet@dimforge.com>2024-03-17 21:20:18 +0100
committerSébastien Crozet <sebcrozet@dimforge.com>2024-03-17 21:24:28 +0100
commitecd308338b189ab569816a38a03e3f8b89669dde (patch)
treefa612abff2f23ea6a5ff04c64c07296d9fb065c8 /src/data
parentda92e5c2837b27433286cf0dd9d887fd44dda254 (diff)
downloadrapier-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.rs2
-rw-r--r--src/data/coarena.rs21
-rw-r--r--src/data/entity_arena.rs145
-rw-r--r--src/data/mod.rs6
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;