Split rigid-bodies and colliders into multiple components
This commit is contained in:
@@ -19,16 +19,16 @@ use std::vec;
|
||||
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
||||
pub struct Arena<T> {
|
||||
items: Vec<Entry<T>>,
|
||||
generation: u64,
|
||||
free_list_head: Option<usize>,
|
||||
generation: u32,
|
||||
free_list_head: Option<u32>,
|
||||
len: usize,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
||||
enum Entry<T> {
|
||||
Free { next_free: Option<usize> },
|
||||
Occupied { generation: u64, value: T },
|
||||
Free { next_free: Option<u32> },
|
||||
Occupied { generation: u32, value: T },
|
||||
}
|
||||
|
||||
/// An index (and generation) into an `Arena`.
|
||||
@@ -48,17 +48,17 @@ enum Entry<T> {
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
||||
pub struct Index {
|
||||
index: usize,
|
||||
generation: u64,
|
||||
index: u32,
|
||||
generation: u32,
|
||||
}
|
||||
|
||||
impl IndexedData for Index {
|
||||
fn default() -> Self {
|
||||
Self::from_raw_parts(crate::INVALID_USIZE, crate::INVALID_U64)
|
||||
Self::from_raw_parts(crate::INVALID_U32, crate::INVALID_U32)
|
||||
}
|
||||
|
||||
fn index(&self) -> usize {
|
||||
self.into_raw_parts().0
|
||||
self.into_raw_parts().0 as usize
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ impl Index {
|
||||
///
|
||||
/// Providing arbitrary values will lead to malformed indices and ultimately
|
||||
/// panics.
|
||||
pub fn from_raw_parts(a: usize, b: u64) -> Index {
|
||||
pub fn from_raw_parts(a: u32, b: u32) -> Index {
|
||||
Index {
|
||||
index: a,
|
||||
generation: b,
|
||||
@@ -84,7 +84,7 @@ impl Index {
|
||||
/// `Index` like `pub struct MyIdentifier(Index);`. However, for external
|
||||
/// types whose definition you can't customize, but which you can construct
|
||||
/// instances of, this method can be useful.
|
||||
pub fn into_raw_parts(self) -> (usize, u64) {
|
||||
pub fn into_raw_parts(self) -> (u32, u32) {
|
||||
(self.index, self.generation)
|
||||
}
|
||||
}
|
||||
@@ -161,7 +161,7 @@ impl<T> Arena<T> {
|
||||
pub fn clear(&mut self) {
|
||||
self.items.clear();
|
||||
|
||||
let end = self.items.capacity();
|
||||
let end = self.items.capacity() as u32;
|
||||
self.items.extend((0..end).map(|i| {
|
||||
if i == end - 1 {
|
||||
Entry::Free { next_free: None }
|
||||
@@ -206,7 +206,7 @@ impl<T> Arena<T> {
|
||||
match self.try_alloc_next_index() {
|
||||
None => Err(value),
|
||||
Some(index) => {
|
||||
self.items[index.index] = Entry::Occupied {
|
||||
self.items[index.index as usize] = Entry::Occupied {
|
||||
generation: self.generation,
|
||||
value,
|
||||
};
|
||||
@@ -247,7 +247,7 @@ impl<T> Arena<T> {
|
||||
match self.try_alloc_next_index() {
|
||||
None => Err(create),
|
||||
Some(index) => {
|
||||
self.items[index.index] = Entry::Occupied {
|
||||
self.items[index.index as usize] = Entry::Occupied {
|
||||
generation: self.generation,
|
||||
value: create(index),
|
||||
};
|
||||
@@ -260,13 +260,13 @@ impl<T> Arena<T> {
|
||||
fn try_alloc_next_index(&mut self) -> Option<Index> {
|
||||
match self.free_list_head {
|
||||
None => None,
|
||||
Some(i) => match self.items[i] {
|
||||
Some(i) => match self.items[i as usize] {
|
||||
Entry::Occupied { .. } => panic!("corrupt free list"),
|
||||
Entry::Free { next_free } => {
|
||||
self.free_list_head = next_free;
|
||||
self.len += 1;
|
||||
Some(Index {
|
||||
index: i,
|
||||
index: i as u32,
|
||||
generation: self.generation,
|
||||
})
|
||||
}
|
||||
@@ -355,14 +355,14 @@ impl<T> Arena<T> {
|
||||
/// assert_eq!(arena.remove(idx), None);
|
||||
/// ```
|
||||
pub fn remove(&mut self, i: Index) -> Option<T> {
|
||||
if i.index >= self.items.len() {
|
||||
if i.index >= self.items.len() as u32 {
|
||||
return None;
|
||||
}
|
||||
|
||||
match self.items[i.index] {
|
||||
match self.items[i.index as usize] {
|
||||
Entry::Occupied { generation, .. } if i.generation == generation => {
|
||||
let entry = mem::replace(
|
||||
&mut self.items[i.index],
|
||||
&mut self.items[i.index as usize],
|
||||
Entry::Free {
|
||||
next_free: self.free_list_head,
|
||||
},
|
||||
@@ -402,8 +402,8 @@ impl<T> Arena<T> {
|
||||
/// assert!(crew_members.next().is_none());
|
||||
/// ```
|
||||
pub fn retain(&mut self, mut predicate: impl FnMut(Index, &mut T) -> bool) {
|
||||
for i in 0..self.capacity() {
|
||||
let remove = match &mut self.items[i] {
|
||||
for i in 0..self.capacity() as u32 {
|
||||
let remove = match &mut self.items[i as usize] {
|
||||
Entry::Occupied { generation, value } => {
|
||||
let index = Index {
|
||||
index: i,
|
||||
@@ -462,7 +462,7 @@ impl<T> Arena<T> {
|
||||
/// assert!(arena.get(idx).is_none());
|
||||
/// ```
|
||||
pub fn get(&self, i: Index) -> Option<&T> {
|
||||
match self.items.get(i.index) {
|
||||
match self.items.get(i.index as usize) {
|
||||
Some(Entry::Occupied { generation, value }) if *generation == i.generation => {
|
||||
Some(value)
|
||||
}
|
||||
@@ -488,7 +488,7 @@ impl<T> Arena<T> {
|
||||
/// assert!(arena.get_mut(idx).is_none());
|
||||
/// ```
|
||||
pub fn get_mut(&mut self, i: Index) -> Option<&mut T> {
|
||||
match self.items.get_mut(i.index) {
|
||||
match self.items.get_mut(i.index as usize) {
|
||||
Some(Entry::Occupied { generation, value }) if *generation == i.generation => {
|
||||
Some(value)
|
||||
}
|
||||
@@ -526,7 +526,7 @@ impl<T> Arena<T> {
|
||||
/// assert_eq!(arena[idx2], 4);
|
||||
/// ```
|
||||
pub fn get2_mut(&mut self, i1: Index, i2: Index) -> (Option<&mut T>, Option<&mut T>) {
|
||||
let len = self.items.len();
|
||||
let len = self.items.len() as u32;
|
||||
|
||||
if i1.index == i2.index {
|
||||
assert!(i1.generation != i2.generation);
|
||||
@@ -544,11 +544,13 @@ impl<T> Arena<T> {
|
||||
}
|
||||
|
||||
let (raw_item1, raw_item2) = {
|
||||
let (xs, ys) = self.items.split_at_mut(cmp::max(i1.index, i2.index));
|
||||
let (xs, ys) = self
|
||||
.items
|
||||
.split_at_mut(cmp::max(i1.index, i2.index) as usize);
|
||||
if i1.index < i2.index {
|
||||
(&mut xs[i1.index], &mut ys[0])
|
||||
(&mut xs[i1.index as usize], &mut ys[0])
|
||||
} else {
|
||||
(&mut ys[0], &mut xs[i2.index])
|
||||
(&mut ys[0], &mut xs[i2.index as usize])
|
||||
}
|
||||
};
|
||||
|
||||
@@ -666,11 +668,11 @@ impl<T> Arena<T> {
|
||||
}
|
||||
} else {
|
||||
Entry::Free {
|
||||
next_free: Some(i + 1),
|
||||
next_free: Some(i as u32 + 1),
|
||||
}
|
||||
}
|
||||
}));
|
||||
self.free_list_head = Some(start);
|
||||
self.free_list_head = Some(start as u32);
|
||||
}
|
||||
|
||||
/// Iterate over shared references to the elements in this arena.
|
||||
@@ -774,7 +776,7 @@ impl<T> Arena<T> {
|
||||
value,
|
||||
Index {
|
||||
generation: *generation,
|
||||
index: i,
|
||||
index: i as u32,
|
||||
},
|
||||
)),
|
||||
_ => None,
|
||||
@@ -797,7 +799,7 @@ impl<T> Arena<T> {
|
||||
value,
|
||||
Index {
|
||||
generation: *generation,
|
||||
index: i,
|
||||
index: i as u32,
|
||||
},
|
||||
)),
|
||||
_ => None,
|
||||
@@ -941,7 +943,10 @@ impl<'a, T> Iterator for Iter<'a, T> {
|
||||
},
|
||||
)) => {
|
||||
self.len -= 1;
|
||||
let idx = Index { index, generation };
|
||||
let idx = Index {
|
||||
index: index as u32,
|
||||
generation,
|
||||
};
|
||||
return Some((idx, value));
|
||||
}
|
||||
None => {
|
||||
@@ -970,7 +975,10 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
|
||||
},
|
||||
)) => {
|
||||
self.len -= 1;
|
||||
let idx = Index { index, generation };
|
||||
let idx = Index {
|
||||
index: index as u32,
|
||||
generation,
|
||||
};
|
||||
return Some((idx, value));
|
||||
}
|
||||
None => {
|
||||
@@ -1039,7 +1047,10 @@ impl<'a, T> Iterator for IterMut<'a, T> {
|
||||
},
|
||||
)) => {
|
||||
self.len -= 1;
|
||||
let idx = Index { index, generation };
|
||||
let idx = Index {
|
||||
index: index as u32,
|
||||
generation,
|
||||
};
|
||||
return Some((idx, value));
|
||||
}
|
||||
None => {
|
||||
@@ -1068,7 +1079,10 @@ impl<'a, T> DoubleEndedIterator for IterMut<'a, T> {
|
||||
},
|
||||
)) => {
|
||||
self.len -= 1;
|
||||
let idx = Index { index, generation };
|
||||
let idx = Index {
|
||||
index: index as u32,
|
||||
generation,
|
||||
};
|
||||
return Some((idx, value));
|
||||
}
|
||||
None => {
|
||||
@@ -1126,7 +1140,10 @@ impl<'a, T> Iterator for Drain<'a, T> {
|
||||
match self.inner.next() {
|
||||
Some((_, Entry::Free { .. })) => continue,
|
||||
Some((index, Entry::Occupied { generation, value })) => {
|
||||
let idx = Index { index, generation };
|
||||
let idx = Index {
|
||||
index: index as u32,
|
||||
generation,
|
||||
};
|
||||
return Some((idx, value));
|
||||
}
|
||||
None => return None,
|
||||
|
||||
@@ -4,7 +4,7 @@ use crate::data::arena::Index;
|
||||
#[derive(Clone, Debug)]
|
||||
/// A container for data associated to item existing into another Arena.
|
||||
pub struct Coarena<T> {
|
||||
data: Vec<(u64, T)>,
|
||||
data: Vec<(u32, T)>,
|
||||
}
|
||||
|
||||
impl<T> Coarena<T> {
|
||||
@@ -17,7 +17,7 @@ impl<T> Coarena<T> {
|
||||
pub fn get(&self, index: Index) -> Option<&T> {
|
||||
let (i, g) = index.into_raw_parts();
|
||||
self.data
|
||||
.get(i)
|
||||
.get(i as usize)
|
||||
.and_then(|(gg, t)| if g == *gg { Some(t) } else { None })
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ impl<T> Coarena<T> {
|
||||
pub fn get_mut(&mut self, index: Index) -> Option<&mut T> {
|
||||
let (i, g) = index.into_raw_parts();
|
||||
self.data
|
||||
.get_mut(i)
|
||||
.get_mut(i as usize)
|
||||
.and_then(|(gg, t)| if g == *gg { Some(t) } else { None })
|
||||
}
|
||||
|
||||
@@ -36,11 +36,11 @@ impl<T> Coarena<T> {
|
||||
{
|
||||
let (i1, g1) = a.into_raw_parts();
|
||||
|
||||
if self.data.len() <= i1 {
|
||||
self.data.resize(i1 + 1, (u32::MAX as u64, T::default()));
|
||||
if self.data.len() <= i1 as usize {
|
||||
self.data.resize(i1 as usize + 1, (u32::MAX, T::default()));
|
||||
}
|
||||
|
||||
self.data[i1] = (g1, value);
|
||||
self.data[i1 as usize] = (g1, value);
|
||||
}
|
||||
|
||||
/// Ensure that elements at the two given indices exist in this coarena, and return their reference.
|
||||
@@ -56,20 +56,22 @@ impl<T> Coarena<T> {
|
||||
assert_ne!(i1, i2, "Cannot index the same object twice.");
|
||||
|
||||
let (elt1, elt2) = if i1 > i2 {
|
||||
if self.data.len() <= i1 {
|
||||
self.data.resize(i1 + 1, (u32::MAX as u64, default.clone()));
|
||||
if self.data.len() <= i1 as usize {
|
||||
self.data
|
||||
.resize(i1 as usize + 1, (u32::MAX, default.clone()));
|
||||
}
|
||||
|
||||
let (left, right) = self.data.split_at_mut(i1);
|
||||
(&mut right[0], &mut left[i2])
|
||||
let (left, right) = self.data.split_at_mut(i1 as usize);
|
||||
(&mut right[0], &mut left[i2 as usize])
|
||||
} else {
|
||||
// i2 > i1
|
||||
if self.data.len() <= i2 {
|
||||
self.data.resize(i2 + 1, (u32::MAX as u64, default.clone()));
|
||||
if self.data.len() <= i2 as usize {
|
||||
self.data
|
||||
.resize(i2 as usize + 1, (u32::MAX, default.clone()));
|
||||
}
|
||||
|
||||
let (left, right) = self.data.split_at_mut(i2);
|
||||
(&mut left[i1], &mut right[0])
|
||||
let (left, right) = self.data.split_at_mut(i2 as usize);
|
||||
(&mut left[i1 as usize], &mut right[0])
|
||||
};
|
||||
|
||||
if elt1.0 != g1 {
|
||||
|
||||
106
src/data/component_set.rs
Normal file
106
src/data/component_set.rs
Normal file
@@ -0,0 +1,106 @@
|
||||
use crate::data::Index;
|
||||
|
||||
// TODO ECS: use this to handle optional components properly.
|
||||
// pub trait OptionalComponentSet<T> {
|
||||
// fn get(&self, handle: Index) -> Option<&T>;
|
||||
// }
|
||||
|
||||
pub trait ComponentSetOption<T> {
|
||||
fn get(&self, handle: Index) -> Option<&T>;
|
||||
}
|
||||
|
||||
pub trait ComponentSet<T>: ComponentSetOption<T> {
|
||||
fn size_hint(&self) -> usize;
|
||||
// TODO ECS: remove this, its only needed by the query pipeline update
|
||||
// which should only take the modified colliders into account.
|
||||
fn for_each(&self, f: impl FnMut(Index, &T));
|
||||
fn index(&self, handle: Index) -> &T {
|
||||
self.get(handle).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ComponentSetMut<T>: ComponentSet<T> {
|
||||
fn map_mut_internal<Result>(
|
||||
&mut self,
|
||||
handle: crate::data::Index,
|
||||
f: impl FnOnce(&mut T) -> Result,
|
||||
) -> Option<Result>;
|
||||
fn set_internal(&mut self, handle: crate::data::Index, val: T);
|
||||
}
|
||||
|
||||
pub trait BundleSet<'a, T> {
|
||||
fn index_bundle(&'a self, handle: Index) -> T;
|
||||
}
|
||||
|
||||
impl<'a, T, A, B> BundleSet<'a, (&'a A, &'a B)> for T
|
||||
where
|
||||
T: ComponentSet<A> + ComponentSet<B>,
|
||||
{
|
||||
#[inline(always)]
|
||||
fn index_bundle(&'a self, handle: Index) -> (&'a A, &'a B) {
|
||||
(self.index(handle), self.index(handle))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T, A, B, C> BundleSet<'a, (&'a A, &'a B, &'a C)> for T
|
||||
where
|
||||
T: ComponentSet<A> + ComponentSet<B> + ComponentSet<C>,
|
||||
{
|
||||
#[inline(always)]
|
||||
fn index_bundle(&'a self, handle: Index) -> (&'a A, &'a B, &'a C) {
|
||||
(self.index(handle), self.index(handle), self.index(handle))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T, A, B, C, D> BundleSet<'a, (&'a A, &'a B, &'a C, &'a D)> for T
|
||||
where
|
||||
T: ComponentSet<A> + ComponentSet<B> + ComponentSet<C> + ComponentSet<D>,
|
||||
{
|
||||
#[inline(always)]
|
||||
fn index_bundle(&'a self, handle: Index) -> (&'a A, &'a B, &'a C, &'a D) {
|
||||
(
|
||||
self.index(handle),
|
||||
self.index(handle),
|
||||
self.index(handle),
|
||||
self.index(handle),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T, A, B, C, D, E> BundleSet<'a, (&'a A, &'a B, &'a C, &'a D, &'a E)> for T
|
||||
where
|
||||
T: ComponentSet<A> + ComponentSet<B> + ComponentSet<C> + ComponentSet<D> + ComponentSet<E>,
|
||||
{
|
||||
#[inline(always)]
|
||||
fn index_bundle(&'a self, handle: Index) -> (&'a A, &'a B, &'a C, &'a D, &'a E) {
|
||||
(
|
||||
self.index(handle),
|
||||
self.index(handle),
|
||||
self.index(handle),
|
||||
self.index(handle),
|
||||
self.index(handle),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T, A, B, C, D, E, F> BundleSet<'a, (&'a A, &'a B, &'a C, &'a D, &'a E, &'a F)> for T
|
||||
where
|
||||
T: ComponentSet<A>
|
||||
+ ComponentSet<B>
|
||||
+ ComponentSet<C>
|
||||
+ ComponentSet<D>
|
||||
+ ComponentSet<E>
|
||||
+ ComponentSet<F>,
|
||||
{
|
||||
#[inline(always)]
|
||||
fn index_bundle(&'a self, handle: Index) -> (&'a A, &'a B, &'a C, &'a D, &'a E, &'a F) {
|
||||
(
|
||||
self.index(handle),
|
||||
self.index(handle),
|
||||
self.index(handle),
|
||||
self.index(handle),
|
||||
self.index(handle),
|
||||
self.index(handle),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,11 @@
|
||||
//! Data structures modified with guaranteed deterministic behavior after deserialization.
|
||||
|
||||
pub use self::arena::{Arena, Index};
|
||||
pub use self::coarena::Coarena;
|
||||
pub use self::component_set::{BundleSet, ComponentSet, ComponentSetMut, ComponentSetOption};
|
||||
|
||||
pub mod arena;
|
||||
mod coarena;
|
||||
mod component_set;
|
||||
pub(crate) mod graph;
|
||||
pub mod pubsub;
|
||||
|
||||
Reference in New Issue
Block a user