diff --git a/src/entities.rs b/src/entities.rs index 79f3eb52..09b8249a 100644 --- a/src/entities.rs +++ b/src/entities.rs @@ -548,9 +548,13 @@ impl EntityMeta { }; } +/// Where an entity is currently stored #[derive(Copy, Clone)] -pub(crate) struct Location { +pub struct Location { + /// Index of the enclosing archetype in [`World::archetypes`](crate::World::archetypes) pub archetype: u32, + /// Index of the entity's components in [`Archetype::get`](crate::Archetype::get) on the + /// associated [`Archetype`](crate::Archetype) pub index: u32, } diff --git a/src/lib.rs b/src/lib.rs index f4095d13..a55bc0e2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -75,7 +75,7 @@ pub use archetype::{Archetype, ArchetypeColumn, ArchetypeColumnMut}; pub use batch::{BatchIncomplete, BatchWriter, ColumnBatch, ColumnBatchBuilder, ColumnBatchType}; pub use bundle::{Bundle, DynamicBundle, DynamicBundleClone, MissingComponent}; pub use command_buffer::CommandBuffer; -pub use entities::{Entity, NoSuchEntity}; +pub use entities::{Entity, Location, NoSuchEntity}; pub use entity_builder::{BuiltEntity, BuiltEntityClone, EntityBuilder, EntityBuilderClone}; pub use entity_ref::{ComponentRef, ComponentRefShared, EntityRef, Ref, RefMut}; pub use query::{ diff --git a/src/query.rs b/src/query.rs index 0521d600..dddb7148 100644 --- a/src/query.rs +++ b/src/query.rs @@ -1081,11 +1081,12 @@ impl PreparedQuery { let state = world .archetypes() + .iter() .enumerate() .filter_map(|(idx, x)| Q::Fetch::prepare(x).map(|state| (idx, state))) .collect(); - let fetch = world.archetypes().map(|_| None).collect(); + let fetch = world.archetypes().iter().map(|_| None).collect(); Self { memo, state, fetch } } @@ -1100,7 +1101,7 @@ impl PreparedQuery { } let meta = world.entities_meta(); - let archetypes = world.archetypes_inner(); + let archetypes = world.archetypes(); PreparedQueryBorrow::new(meta, archetypes, &self.state, &mut self.fetch) } @@ -1116,7 +1117,7 @@ impl PreparedQuery { } let meta = world.entities_meta(); - let archetypes = world.archetypes_inner(); + let archetypes = world.archetypes(); let state: &'q [(usize, ::State)] = unsafe { mem::transmute(&*self.state) }; @@ -1133,7 +1134,7 @@ impl PreparedQuery { } let meta = world.entities_meta(); - let archetypes = world.archetypes_inner(); + let archetypes = world.archetypes(); let state: &'q [(usize, ::State)] = unsafe { mem::transmute(&*self.state) }; diff --git a/src/serialize/column.rs b/src/serialize/column.rs index de0728bc..1e8f0504 100644 --- a/src/serialize/column.rs +++ b/src/serialize/column.rs @@ -291,8 +291,9 @@ where } let predicate = |x: &&Archetype| -> bool { !x.is_empty() && x.satisfies::() }; - let mut seq = serializer.serialize_seq(Some(world.archetypes().filter(predicate).count()))?; - for archetype in world.archetypes().filter(predicate) { + let mut seq = + serializer.serialize_seq(Some(world.archetypes().iter().filter(predicate).count()))?; + for archetype in world.archetypes().iter().filter(predicate) { seq.serialize_element(&SerializeArchetype { world, archetype, diff --git a/src/serialize/row.rs b/src/serialize/row.rs index e3c6b06a..5b44fa88 100644 --- a/src/serialize/row.rs +++ b/src/serialize/row.rs @@ -117,6 +117,7 @@ where { let entity_count = world .archetypes() + .iter() .filter(|a| a.satisfies::()) .map(|a| a.len() as usize) .sum(); diff --git a/src/world.rs b/src/world.rs index 6352f601..5936358e 100644 --- a/src/world.rs +++ b/src/world.rs @@ -416,7 +416,11 @@ impl World { &self.entities.meta } - pub(crate) fn archetypes_inner(&self) -> &[Archetype] { + /// Inspect the archetypes that entities are organized into + /// + /// Useful for dynamically scheduling concurrent queries by checking borrows in advance, and for + /// efficient serialization. + pub fn archetypes(&self) -> &[Archetype] { &self.archetypes.archetypes } @@ -500,6 +504,15 @@ impl World { } } + /// Storage location of `entity` + /// + /// Useful in combination with [`archetypes`](Self::archetypes). May be invalidated when + /// [`archetypes_generation`](Self::archetypes_generation) changes. + #[inline] + pub fn location_of(&self, entity: Entity) -> Result { + self.entities.get(entity) + } + /// Given an id obtained from [`Entity::id`], reconstruct the still-live [`Entity`]. /// /// # Safety @@ -818,14 +831,6 @@ impl World { .flush(|id, location| location.index = unsafe { arch.allocate(id) }); } - /// Inspect the archetypes that entities are organized into - /// - /// Useful for dynamically scheduling concurrent queries by checking borrows in advance, and for - /// efficient serialization. - pub fn archetypes(&self) -> impl ExactSizeIterator + '_ { - self.archetypes_inner().iter() - } - /// Despawn `entity`, yielding a [`DynamicBundle`] of its components /// /// Useful for moving entities between worlds. diff --git a/tests/tests.rs b/tests/tests.rs index 122da18d..17780637 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -858,7 +858,7 @@ fn columnar_access() { let e = world.spawn(("abc", 123)); let f = world.spawn(("def", 456, true)); let g = world.spawn(("ghi", 789, false)); - let mut archetypes = world.archetypes(); + let mut archetypes = world.archetypes().iter(); let _empty = archetypes.next().unwrap(); let a = archetypes.next().unwrap(); assert_eq!(a.ids(), &[e.id()]);