mod query_set; pub use query_set::*; use crate::{ ArchetypeComponent, Batch, BatchedIter, Component, ComponentError, Entity, Fetch, Mut, QueryFilter, QueryIter, ReadOnlyFetch, TypeAccess, World, WorldQuery, }; use bevy_tasks::ParallelIterator; use std::marker::PhantomData; /// Provides scoped access to a World according to a given [HecsQuery] #[derive(Debug)] pub struct Query<'a, Q: WorldQuery, F: QueryFilter = ()> { pub(crate) world: &'a World, pub(crate) component_access: &'a TypeAccess, _marker: PhantomData<(Q, F)>, } /// An error that occurs when using a [Query] #[derive(Debug)] pub enum QueryError { CannotReadArchetype, CannotWriteArchetype, ComponentError(ComponentError), NoSuchEntity, } impl<'a, Q: WorldQuery, F: QueryFilter> Query<'a, Q, F> { /// # Safety /// This will create a Query that could violate memory safety rules. Make sure that this is only called in /// ways that ensure the Queries have unique mutable access. #[inline] pub(crate) unsafe fn new( world: &'a World, component_access: &'a TypeAccess, ) -> Self { Self { world, component_access, _marker: PhantomData::default(), } } /// Iterates over the query results. This can only be called for read-only queries #[inline] pub fn iter(&self) -> QueryIter<'_, Q, F> where Q::Fetch: ReadOnlyFetch, { // SAFE: system runs without conflicts with other systems. same-system queries have runtime borrow checks when they conflict unsafe { self.world.query_unchecked() } } /// Iterates over the query results #[inline] pub fn iter_mut(&mut self) -> QueryIter<'_, Q, F> { // SAFE: system runs without conflicts with other systems. same-system queries have runtime borrow checks when they conflict unsafe { self.world.query_unchecked() } } /// Iterates over the query results /// # Safety /// This allows aliased mutability. You must make sure this call does not result in multiple mutable references to the same component #[inline] pub unsafe fn iter_unsafe(&self) -> QueryIter<'_, Q, F> { // SAFE: system runs without conflicts with other systems. same-system queries have runtime borrow checks when they conflict self.world.query_unchecked() } #[inline] pub fn par_iter(&self, batch_size: usize) -> ParIter<'_, Q, F> where Q::Fetch: ReadOnlyFetch, { // SAFE: system runs without conflicts with other systems. same-system queries have runtime borrow checks when they conflict unsafe { ParIter::new(self.world.query_batched_unchecked(batch_size)) } } #[inline] pub fn par_iter_mut(&mut self, batch_size: usize) -> ParIter<'_, Q, F> { // SAFE: system runs without conflicts with other systems. same-system queries have runtime borrow checks when they conflict unsafe { ParIter::new(self.world.query_batched_unchecked(batch_size)) } } /// Gets the query result for the given `entity` #[inline] pub fn get(&self, entity: Entity) -> Result<::Item, QueryError> where Q::Fetch: ReadOnlyFetch, { // SAFE: system runs without conflicts with other systems. same-system queries have runtime borrow checks when they conflict unsafe { self.world .query_one_unchecked::(entity) .map_err(|_err| QueryError::NoSuchEntity) } } /// Gets the query result for the given `entity` #[inline] pub fn get_mut(&mut self, entity: Entity) -> Result<::Item, QueryError> { // SAFE: system runs without conflicts with other systems. same-system queries have runtime borrow checks when they conflict unsafe { self.world .query_one_unchecked::(entity) .map_err(|_err| QueryError::NoSuchEntity) } } /// Gets the query result for the given `entity` /// # Safety /// This allows aliased mutability. You must make sure this call does not result in multiple mutable references to the same component #[inline] pub unsafe fn get_unsafe( &self, entity: Entity, ) -> Result<::Item, QueryError> { self.world .query_one_unchecked::(entity) .map_err(|_err| QueryError::NoSuchEntity) } /// Gets a reference to the entity's component of the given type. This will fail if the entity does not have /// the given component type or if the given component type does not match this query. pub fn get_component(&self, entity: Entity) -> Result<&T, QueryError> { if let Some(location) = self.world.get_entity_location(entity) { if self .component_access .is_read_or_write(&ArchetypeComponent::new::(location.archetype)) { // SAFE: we have already checked that the entity/component matches our archetype access. and systems are scheduled to run with safe archetype access unsafe { self.world .get_at_location_unchecked(location) .map_err(QueryError::ComponentError) } } else { Err(QueryError::CannotReadArchetype) } } else { Err(QueryError::ComponentError(ComponentError::NoSuchEntity)) } } /// Gets a mutable reference to the entity's component of the given type. This will fail if the entity does not have /// the given component type or if the given component type does not match this query. pub fn get_component_mut( &mut self, entity: Entity, ) -> Result, QueryError> { let location = match self.world.get_entity_location(entity) { None => return Err(QueryError::ComponentError(ComponentError::NoSuchEntity)), Some(location) => location, }; if self .component_access .is_write(&ArchetypeComponent::new::(location.archetype)) { // SAFE: RefMut does exclusivity checks and we have already validated the entity unsafe { self.world .get_mut_at_location_unchecked(location) .map_err(QueryError::ComponentError) } } else { Err(QueryError::CannotWriteArchetype) } } /// Gets a mutable reference to the entity's component of the given type. This will fail if the entity does not have /// the given component type /// # Safety /// This allows aliased mutability. You must make sure this call does not result in multiple mutable references to the same component pub unsafe fn get_component_unsafe( &self, entity: Entity, ) -> Result, QueryError> { self.world .get_mut_unchecked(entity) .map_err(QueryError::ComponentError) } /// Returns an array containing the `Entity`s in this `Query` that had the given `Component` /// removed in this update. /// /// `removed::()` only returns entities whose components were removed before the /// current system started. /// /// Regular systems do not apply `Commands` until the end of their stage. This means component /// removals in a regular system won't be accessible through `removed::()` in the same /// stage, because the removal hasn't actually occurred yet. This can be solved by executing /// `removed::()` in a later stage. `AppBuilder::add_system_to_stage()` can be used to /// control at what stage a system runs. /// /// Thread local systems manipulate the world directly, so removes are applied immediately. This /// means any system that runs after a thread local system in the same update will pick up /// removals that happened in the thread local system, regardless of stages. pub fn removed(&self) -> &[Entity] { self.world.removed::() } /// Sets the entity's component to the given value. This will fail if the entity does not already have /// the given component type or if the given component type does not match this query. pub fn set(&mut self, entity: Entity, component: T) -> Result<(), QueryError> { let mut current = self.get_component_mut::(entity)?; *current = component; Ok(()) } } /// Parallel version of QueryIter pub struct ParIter<'w, Q: WorldQuery, F: QueryFilter> { batched_iter: BatchedIter<'w, Q, F>, } impl<'w, Q: WorldQuery, F: QueryFilter> ParIter<'w, Q, F> { pub fn new(batched_iter: BatchedIter<'w, Q, F>) -> Self { Self { batched_iter } } } unsafe impl<'w, Q: WorldQuery, F: QueryFilter> Send for ParIter<'w, Q, F> {} impl<'w, Q: WorldQuery, F: QueryFilter> ParallelIterator> for ParIter<'w, Q, F> { type Item = >::Item; #[inline] fn next_batch(&mut self) -> Option> { self.batched_iter.next() } }