mirror of
https://github.com/lisk77/comet.git
synced 2025-12-12 09:08:49 +00:00
fix(ecs): entity deletion is now type correct
This commit is contained in:
parent
607bf94f1e
commit
2a37205c22
4 changed files with 77 additions and 3 deletions
|
|
@ -112,9 +112,7 @@ impl Scene {
|
||||||
self.remove_entity_from_archetype(entity_id.index, self.get_component_set(idx));
|
self.remove_entity_from_archetype(entity_id.index, self.get_component_set(idx));
|
||||||
self.entities[idx] = None;
|
self.entities[idx] = None;
|
||||||
info!("Deleted entity! ID: {}", entity_id.index);
|
info!("Deleted entity! ID: {}", entity_id.index);
|
||||||
for (_, value) in self.components.iter_mut() {
|
self.components.remove_entity(idx);
|
||||||
value.remove::<u8>(idx);
|
|
||||||
}
|
|
||||||
if let Some(gen) = self.generations.get_mut(idx) {
|
if let Some(gen) = self.generations.get_mut(idx) {
|
||||||
*gen = gen.wrapping_add(1);
|
*gen = gen.wrapping_add(1);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -272,6 +272,17 @@ impl Column {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Remove an element without knowing its concrete type. Drops in place.
|
||||||
|
pub fn remove_any(&mut self, index: usize) {
|
||||||
|
if index >= self.data.len() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
unsafe {
|
||||||
|
let ptr = self.data.swap_remove_and_forget_unchecked(index);
|
||||||
|
(self.data.drop)(ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Overwrites an existing element in place, dropping the previous value.
|
/// Overwrites an existing element in place, dropping the previous value.
|
||||||
pub fn set<T: 'static>(&mut self, index: usize, item: T) -> Option<()> {
|
pub fn set<T: 'static>(&mut self, index: usize, item: T) -> Option<()> {
|
||||||
assert_eq!(TypeId::of::<T>(), TypeId::of::<T>(), "Type mismatch");
|
assert_eq!(TypeId::of::<T>(), TypeId::of::<T>(), "Type mismatch");
|
||||||
|
|
|
||||||
|
|
@ -55,4 +55,11 @@ impl ComponentStorage {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Removes all components belonging to the given entity index.
|
||||||
|
pub fn remove_entity(&mut self, index: usize) {
|
||||||
|
for (_, value) in self.iter_mut() {
|
||||||
|
value.remove_any(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,64 @@ impl SparseSet {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Removes an element by external index without knowing its type. Returns true if something was removed.
|
||||||
|
pub fn remove_any(&mut self, index: usize) -> bool {
|
||||||
|
if let Some(page_vec) = self
|
||||||
|
.sparse
|
||||||
|
.get(index / self.page_size)
|
||||||
|
.and_then(|x| x.as_ref())
|
||||||
|
{
|
||||||
|
if let Some(sparse_index) = page_vec
|
||||||
|
.get(index % self.page_size)
|
||||||
|
.and_then(|x| x.as_ref())
|
||||||
|
{
|
||||||
|
let dense_index = *sparse_index;
|
||||||
|
let last_dense_index = self.dense.data.len() - 1;
|
||||||
|
|
||||||
|
if dense_index != last_dense_index {
|
||||||
|
if let Some(ext_index) = self.find_external_index(last_dense_index) {
|
||||||
|
if let Some(page_vec) = self
|
||||||
|
.sparse
|
||||||
|
.get_mut(ext_index / self.page_size)
|
||||||
|
.and_then(|x| x.as_mut())
|
||||||
|
{
|
||||||
|
page_vec[ext_index % self.page_size] = Some(dense_index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.dense.swap(dense_index, last_dense_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(page_vec) = self
|
||||||
|
.sparse
|
||||||
|
.get_mut(index / self.page_size)
|
||||||
|
.and_then(|x| x.as_mut())
|
||||||
|
{
|
||||||
|
page_vec[index % self.page_size] = None;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.dense.remove_any(dense_index);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Finds the external index that maps to a given dense index.
|
||||||
|
fn find_external_index(&self, dense_index: usize) -> Option<usize> {
|
||||||
|
for (page_idx, page_opt) in self.sparse.iter().enumerate() {
|
||||||
|
if let Some(page) = page_opt {
|
||||||
|
for (offset, entry) in page.iter().enumerate() {
|
||||||
|
if let Some(idx) = entry {
|
||||||
|
if *idx == dense_index {
|
||||||
|
return Some(page_idx * self.page_size + offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get<T: 'static>(&self, index: usize) -> Option<&T> {
|
pub fn get<T: 'static>(&self, index: usize) -> Option<&T> {
|
||||||
if let Some(page_vec) = self
|
if let Some(page_vec) = self
|
||||||
.sparse
|
.sparse
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue