From ba2916c45a6dcf23f7c4007e7ef2a6b0df393433 Mon Sep 17 00:00:00 2001 From: Boxy Date: Wed, 21 Jul 2021 21:42:52 +0000 Subject: [PATCH] move `get_insert_bundle_info` (#2508) I had to move this out in my relations PR and its causing a large diff so I figure I could just do this separately --- crates/bevy_ecs/src/world/entity_ref.rs | 138 ++++++++++++------------ 1 file changed, 69 insertions(+), 69 deletions(-) diff --git a/crates/bevy_ecs/src/world/entity_ref.rs b/crates/bevy_ecs/src/world/entity_ref.rs index 1815d15798..11a0a8b842 100644 --- a/crates/bevy_ecs/src/world/entity_ref.rs +++ b/crates/bevy_ecs/src/world/entity_ref.rs @@ -189,76 +189,76 @@ impl<'w> EntityMut<'w> { }) } + /// # Safety: + /// Partially moves the entity to a new archetype based on the provided bundle info + /// You must handle the other part of moving the entity yourself + unsafe fn get_insert_bundle_info<'a>( + entities: &mut Entities, + archetypes: &'a mut Archetypes, + components: &mut Components, + storages: &mut Storages, + bundle_info: &BundleInfo, + current_location: EntityLocation, + entity: Entity, + ) -> (&'a Archetype, &'a Vec, EntityLocation) { + // SAFE: component ids in `bundle_info` and self.location are valid + let new_archetype_id = add_bundle_to_archetype( + archetypes, + storages, + components, + current_location.archetype_id, + bundle_info, + ); + if new_archetype_id == current_location.archetype_id { + let archetype = &archetypes[current_location.archetype_id]; + let edge = archetype.edges().get_add_bundle(bundle_info.id).unwrap(); + (archetype, &edge.bundle_status, current_location) + } else { + let (old_table_row, old_table_id) = { + let old_archetype = &mut archetypes[current_location.archetype_id]; + let result = old_archetype.swap_remove(current_location.index); + if let Some(swapped_entity) = result.swapped_entity { + entities.meta[swapped_entity.id as usize].location = current_location; + } + (result.table_row, old_archetype.table_id()) + }; + + let new_table_id = archetypes[new_archetype_id].table_id(); + + let new_location = if old_table_id == new_table_id { + archetypes[new_archetype_id].allocate(entity, old_table_row) + } else { + let (old_table, new_table) = storages.tables.get_2_mut(old_table_id, new_table_id); + // PERF: store "non bundle" components in edge, then just move those to avoid + // redundant copies + let move_result = old_table.move_to_superset_unchecked(old_table_row, new_table); + + let new_location = + archetypes[new_archetype_id].allocate(entity, move_result.new_row); + // if an entity was moved into this entity's table spot, update its table row + if let Some(swapped_entity) = move_result.swapped_entity { + let swapped_location = entities.get(swapped_entity).unwrap(); + archetypes[swapped_location.archetype_id] + .set_entity_table_row(swapped_location.index, old_table_row); + } + new_location + }; + + entities.meta[entity.id as usize].location = new_location; + let (old_archetype, new_archetype) = + archetypes.get_2_mut(current_location.archetype_id, new_archetype_id); + let edge = old_archetype + .edges() + .get_add_bundle(bundle_info.id) + .unwrap(); + (&*new_archetype, &edge.bundle_status, new_location) + + // Sparse set components are intentionally ignored here. They don't need to move + } + } + // TODO: move relevant methods to World (add/remove bundle) pub fn insert_bundle(&mut self, bundle: T) -> &mut Self { - // Use a non-generic function to cut down on monomorphization - unsafe fn get_insert_bundle_info<'a>( - entities: &mut Entities, - archetypes: &'a mut Archetypes, - components: &mut Components, - storages: &mut Storages, - bundle_info: &BundleInfo, - current_location: EntityLocation, - entity: Entity, - ) -> (&'a Archetype, &'a Vec, EntityLocation) { - // SAFE: component ids in `bundle_info` and self.location are valid - let new_archetype_id = add_bundle_to_archetype( - archetypes, - storages, - components, - current_location.archetype_id, - bundle_info, - ); - if new_archetype_id == current_location.archetype_id { - let archetype = &archetypes[current_location.archetype_id]; - let edge = archetype.edges().get_add_bundle(bundle_info.id).unwrap(); - (archetype, &edge.bundle_status, current_location) - } else { - let (old_table_row, old_table_id) = { - let old_archetype = &mut archetypes[current_location.archetype_id]; - let result = old_archetype.swap_remove(current_location.index); - if let Some(swapped_entity) = result.swapped_entity { - entities.meta[swapped_entity.id as usize].location = current_location; - } - (result.table_row, old_archetype.table_id()) - }; - - let new_table_id = archetypes[new_archetype_id].table_id(); - - let new_location = if old_table_id == new_table_id { - archetypes[new_archetype_id].allocate(entity, old_table_row) - } else { - let (old_table, new_table) = - storages.tables.get_2_mut(old_table_id, new_table_id); - // PERF: store "non bundle" components in edge, then just move those to avoid - // redundant copies - let move_result = - old_table.move_to_superset_unchecked(old_table_row, new_table); - - let new_location = - archetypes[new_archetype_id].allocate(entity, move_result.new_row); - // if an entity was moved into this entity's table spot, update its table row - if let Some(swapped_entity) = move_result.swapped_entity { - let swapped_location = entities.get(swapped_entity).unwrap(); - archetypes[swapped_location.archetype_id] - .set_entity_table_row(swapped_location.index, old_table_row); - } - new_location - }; - - entities.meta[entity.id as usize].location = new_location; - let (old_archetype, new_archetype) = - archetypes.get_2_mut(current_location.archetype_id, new_archetype_id); - let edge = old_archetype - .edges() - .get_add_bundle(bundle_info.id) - .unwrap(); - (&*new_archetype, &edge.bundle_status, new_location) - - // Sparse set components are intentionally ignored here. They don't need to move - } - } - let change_tick = self.world.change_tick(); let bundle_info = self .world @@ -266,7 +266,7 @@ impl<'w> EntityMut<'w> { .init_info::(&mut self.world.components); let (archetype, bundle_status, new_location) = unsafe { - get_insert_bundle_info( + Self::get_insert_bundle_info( &mut self.world.entities, &mut self.world.archetypes, &mut self.world.components,