This commit is contained in:
Chris Russell 2025-07-18 07:14:25 -04:00 committed by GitHub
commit 78c9e752aa
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 277 additions and 267 deletions

View File

@ -408,10 +408,7 @@ impl<A: Animatable> AnimationCurveEvaluator for AnimatableCurveEvaluator<A> {
self.evaluator.push_blend_register(weight, graph_node) self.evaluator.push_blend_register(weight, graph_node)
} }
fn commit<'a>( fn commit(&mut self, mut entity: AnimationEntityMut) -> Result<(), AnimationEvaluationError> {
&mut self,
mut entity: AnimationEntityMut<'a>,
) -> Result<(), AnimationEvaluationError> {
let property = self.property.get_mut(&mut entity)?; let property = self.property.get_mut(&mut entity)?;
*property = self *property = self
.evaluator .evaluator
@ -596,10 +593,7 @@ impl AnimationCurveEvaluator for WeightsCurveEvaluator {
Ok(()) Ok(())
} }
fn commit<'a>( fn commit(&mut self, mut entity: AnimationEntityMut) -> Result<(), AnimationEvaluationError> {
&mut self,
mut entity: AnimationEntityMut<'a>,
) -> Result<(), AnimationEvaluationError> {
if self.stack_morph_target_weights.is_empty() { if self.stack_morph_target_weights.is_empty() {
return Ok(()); return Ok(());
} }
@ -905,10 +899,7 @@ pub trait AnimationCurveEvaluator: Downcast + Send + Sync + 'static {
/// ///
/// The property on the component must be overwritten with the value from /// The property on the component must be overwritten with the value from
/// the stack, not blended with it. /// the stack, not blended with it.
fn commit<'a>( fn commit(&mut self, entity: AnimationEntityMut) -> Result<(), AnimationEvaluationError>;
&mut self,
entity: AnimationEntityMut<'a>,
) -> Result<(), AnimationEvaluationError>;
} }
impl_downcast!(AnimationCurveEvaluator); impl_downcast!(AnimationCurveEvaluator);

View File

@ -1021,8 +1021,8 @@ pub fn advance_animations(
} }
/// A type alias for [`EntityMutExcept`] as used in animation. /// A type alias for [`EntityMutExcept`] as used in animation.
pub type AnimationEntityMut<'w> = pub type AnimationEntityMut<'w, 's> =
EntityMutExcept<'w, (AnimationTarget, AnimationPlayer, AnimationGraphHandle)>; EntityMutExcept<'w, 's, (AnimationTarget, AnimationPlayer, AnimationGraphHandle)>;
/// A system that modifies animation targets (e.g. bones in a skinned mesh) /// A system that modifies animation targets (e.g. bones in a skinned mesh)
/// according to the currently-playing animations. /// according to the currently-playing animations.

View File

@ -165,6 +165,32 @@ impl<T: SparseSetIndex> Access<T> {
} }
} }
/// Creates an [`Access`] with read access to all components.
/// This is equivalent to calling `read_all()` on `Access::new()`,
/// but is available in a `const` context.
pub(crate) const fn new_read_all() -> Self {
let mut access = Self::new();
access.reads_all_resources = true;
// Note that we cannot use `read_all_components()`
// because `FixedBitSet::clear()` is not `const`.
access.component_read_and_writes_inverted = true;
access
}
/// Creates an [`Access`] with read access to all components.
/// This is equivalent to calling `read_all()` on `Access::new()`,
/// but is available in a `const` context.
pub(crate) const fn new_write_all() -> Self {
let mut access = Self::new();
access.reads_all_resources = true;
access.writes_all_resources = true;
// Note that we cannot use `write_all_components()`
// because `FixedBitSet::clear()` is not `const`.
access.component_read_and_writes_inverted = true;
access.component_writes_inverted = true;
access
}
fn add_component_sparse_set_index_read(&mut self, index: usize) { fn add_component_sparse_set_index_read(&mut self, index: usize) {
if !self.component_read_and_writes_inverted { if !self.component_read_and_writes_inverted {
self.component_read_and_writes.grow_and_insert(index); self.component_read_and_writes.grow_and_insert(index);

View File

@ -14,7 +14,6 @@ use crate::{
use bevy_ptr::{ThinSlicePtr, UnsafeCellDeref}; use bevy_ptr::{ThinSlicePtr, UnsafeCellDeref};
use bevy_utils::prelude::DebugName; use bevy_utils::prelude::DebugName;
use core::{cell::UnsafeCell, marker::PhantomData, panic::Location}; use core::{cell::UnsafeCell, marker::PhantomData, panic::Location};
use smallvec::SmallVec;
use variadics_please::all_tuples; use variadics_please::all_tuples;
/// Types that can be fetched from a [`World`] using a [`Query`]. /// Types that can be fetched from a [`World`] using a [`Query`].
@ -921,8 +920,8 @@ impl ReleaseStateQueryData for EntityMut<'_> {
} }
/// SAFETY: The accesses of `Self::ReadOnly` are a subset of the accesses of `Self` /// SAFETY: The accesses of `Self::ReadOnly` are a subset of the accesses of `Self`
unsafe impl<'a> WorldQuery for FilteredEntityRef<'a> { unsafe impl WorldQuery for FilteredEntityRef<'_, '_> {
type Fetch<'w> = (EntityFetch<'w>, Access<ComponentId>); type Fetch<'w> = EntityFetch<'w>;
type State = Access<ComponentId>; type State = Access<ComponentId>;
fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {
@ -937,31 +936,28 @@ unsafe impl<'a> WorldQuery for FilteredEntityRef<'a> {
last_run: Tick, last_run: Tick,
this_run: Tick, this_run: Tick,
) -> Self::Fetch<'w> { ) -> Self::Fetch<'w> {
let mut access = Access::default(); EntityFetch {
access.read_all_components(); world,
( last_run,
EntityFetch { this_run,
world, }
last_run,
this_run,
},
access,
)
} }
#[inline] #[inline]
unsafe fn set_archetype<'w, 's>( unsafe fn set_archetype<'w, 's>(
fetch: &mut Self::Fetch<'w>, _fetch: &mut Self::Fetch<'w>,
state: &'s Self::State, _state: &'s Self::State,
_: &'w Archetype, _: &'w Archetype,
_table: &Table, _table: &Table,
) { ) {
fetch.1.clone_from(state);
} }
#[inline] #[inline]
unsafe fn set_table<'w, 's>(fetch: &mut Self::Fetch<'w>, state: &'s Self::State, _: &'w Table) { unsafe fn set_table<'w, 's>(
fetch.1.clone_from(state); _fetch: &mut Self::Fetch<'w>,
_state: &'s Self::State,
_: &'w Table,
) {
} }
fn update_component_access( fn update_component_access(
@ -992,10 +988,10 @@ unsafe impl<'a> WorldQuery for FilteredEntityRef<'a> {
} }
/// SAFETY: `Self` is the same as `Self::ReadOnly` /// SAFETY: `Self` is the same as `Self::ReadOnly`
unsafe impl<'a> QueryData for FilteredEntityRef<'a> { unsafe impl QueryData for FilteredEntityRef<'_, '_> {
const IS_READ_ONLY: bool = true; const IS_READ_ONLY: bool = true;
type ReadOnly = Self; type ReadOnly = Self;
type Item<'w, 's> = FilteredEntityRef<'w>; type Item<'w, 's> = FilteredEntityRef<'w, 's>;
fn shrink<'wlong: 'wshort, 'wshort, 's>( fn shrink<'wlong: 'wshort, 'wshort, 's>(
item: Self::Item<'wlong, 's>, item: Self::Item<'wlong, 's>,
@ -1024,8 +1020,8 @@ unsafe impl<'a> QueryData for FilteredEntityRef<'a> {
#[inline(always)] #[inline(always)]
unsafe fn fetch<'w, 's>( unsafe fn fetch<'w, 's>(
_state: &'s Self::State, access: &'s Self::State,
(fetch, access): &mut Self::Fetch<'w>, fetch: &mut Self::Fetch<'w>,
entity: Entity, entity: Entity,
_table_row: TableRow, _table_row: TableRow,
) -> Self::Item<'w, 's> { ) -> Self::Item<'w, 's> {
@ -1037,16 +1033,16 @@ unsafe impl<'a> QueryData for FilteredEntityRef<'a> {
.debug_checked_unwrap() .debug_checked_unwrap()
}; };
// SAFETY: mutable access to every component has been registered. // SAFETY: mutable access to every component has been registered.
unsafe { FilteredEntityRef::new(cell, access.clone()) } unsafe { FilteredEntityRef::new(cell, access) }
} }
} }
/// SAFETY: Access is read-only. /// SAFETY: Access is read-only.
unsafe impl ReadOnlyQueryData for FilteredEntityRef<'_> {} unsafe impl ReadOnlyQueryData for FilteredEntityRef<'_, '_> {}
/// SAFETY: The accesses of `Self::ReadOnly` are a subset of the accesses of `Self` /// SAFETY: The accesses of `Self::ReadOnly` are a subset of the accesses of `Self`
unsafe impl<'a> WorldQuery for FilteredEntityMut<'a> { unsafe impl WorldQuery for FilteredEntityMut<'_, '_> {
type Fetch<'w> = (EntityFetch<'w>, Access<ComponentId>); type Fetch<'w> = EntityFetch<'w>;
type State = Access<ComponentId>; type State = Access<ComponentId>;
fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {
@ -1061,31 +1057,28 @@ unsafe impl<'a> WorldQuery for FilteredEntityMut<'a> {
last_run: Tick, last_run: Tick,
this_run: Tick, this_run: Tick,
) -> Self::Fetch<'w> { ) -> Self::Fetch<'w> {
let mut access = Access::default(); EntityFetch {
access.write_all_components(); world,
( last_run,
EntityFetch { this_run,
world, }
last_run,
this_run,
},
access,
)
} }
#[inline] #[inline]
unsafe fn set_archetype<'w, 's>( unsafe fn set_archetype<'w, 's>(
fetch: &mut Self::Fetch<'w>, _fetch: &mut Self::Fetch<'w>,
state: &'s Self::State, _state: &'s Self::State,
_: &'w Archetype, _: &'w Archetype,
_table: &Table, _table: &Table,
) { ) {
fetch.1.clone_from(state);
} }
#[inline] #[inline]
unsafe fn set_table<'w, 's>(fetch: &mut Self::Fetch<'w>, state: &'s Self::State, _: &'w Table) { unsafe fn set_table<'w, 's>(
fetch.1.clone_from(state); _fetch: &mut Self::Fetch<'w>,
_state: &'s Self::State,
_: &'w Table,
) {
} }
fn update_component_access( fn update_component_access(
@ -1116,10 +1109,10 @@ unsafe impl<'a> WorldQuery for FilteredEntityMut<'a> {
} }
/// SAFETY: access of `FilteredEntityRef` is a subset of `FilteredEntityMut` /// SAFETY: access of `FilteredEntityRef` is a subset of `FilteredEntityMut`
unsafe impl<'a> QueryData for FilteredEntityMut<'a> { unsafe impl<'a, 'b> QueryData for FilteredEntityMut<'a, 'b> {
const IS_READ_ONLY: bool = false; const IS_READ_ONLY: bool = false;
type ReadOnly = FilteredEntityRef<'a>; type ReadOnly = FilteredEntityRef<'a, 'b>;
type Item<'w, 's> = FilteredEntityMut<'w>; type Item<'w, 's> = FilteredEntityMut<'w, 's>;
fn shrink<'wlong: 'wshort, 'wshort, 's>( fn shrink<'wlong: 'wshort, 'wshort, 's>(
item: Self::Item<'wlong, 's>, item: Self::Item<'wlong, 's>,
@ -1146,8 +1139,8 @@ unsafe impl<'a> QueryData for FilteredEntityMut<'a> {
#[inline(always)] #[inline(always)]
unsafe fn fetch<'w, 's>( unsafe fn fetch<'w, 's>(
_state: &'s Self::State, access: &'s Self::State,
(fetch, access): &mut Self::Fetch<'w>, fetch: &mut Self::Fetch<'w>,
entity: Entity, entity: Entity,
_table_row: TableRow, _table_row: TableRow,
) -> Self::Item<'w, 's> { ) -> Self::Item<'w, 's> {
@ -1159,19 +1152,19 @@ unsafe impl<'a> QueryData for FilteredEntityMut<'a> {
.debug_checked_unwrap() .debug_checked_unwrap()
}; };
// SAFETY: mutable access to every component has been registered. // SAFETY: mutable access to every component has been registered.
unsafe { FilteredEntityMut::new(cell, access.clone()) } unsafe { FilteredEntityMut::new(cell, access) }
} }
} }
/// SAFETY: `EntityRefExcept` guards access to all components in the bundle `B` /// SAFETY: `EntityRefExcept` guards access to all components in the bundle `B`
/// and populates `Access` values so that queries that conflict with this access /// and populates `Access` values so that queries that conflict with this access
/// are rejected. /// are rejected.
unsafe impl<'a, B> WorldQuery for EntityRefExcept<'a, B> unsafe impl<'a, 'b, B> WorldQuery for EntityRefExcept<'a, 'b, B>
where where
B: Bundle, B: Bundle,
{ {
type Fetch<'w> = EntityFetch<'w>; type Fetch<'w> = EntityFetch<'w>;
type State = SmallVec<[ComponentId; 4]>; type State = Access<ComponentId>;
fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {
fetch fetch
@ -1206,33 +1199,39 @@ where
state: &Self::State, state: &Self::State,
filtered_access: &mut FilteredAccess<ComponentId>, filtered_access: &mut FilteredAccess<ComponentId>,
) { ) {
let mut my_access = Access::new();
my_access.read_all_components();
for id in state {
my_access.remove_component_read(*id);
}
let access = filtered_access.access_mut(); let access = filtered_access.access_mut();
assert!( assert!(
access.is_compatible(&my_access), access.is_compatible(state),
"`EntityRefExcept<{}>` conflicts with a previous access in this query.", "`EntityRefExcept<{}>` conflicts with a previous access in this query.",
DebugName::type_name::<B>(), DebugName::type_name::<B>(),
); );
access.extend(&my_access); access.extend(state);
} }
fn init_state(world: &mut World) -> Self::State { fn init_state(world: &mut World) -> Self::State {
Self::get_state(world.components()).unwrap() let mut access = Access::new();
access.read_all_components();
B::component_ids(&mut world.components_registrator(), &mut |id| {
access.remove_component_read(id);
});
access
} }
fn get_state(components: &Components) -> Option<Self::State> { fn get_state(components: &Components) -> Option<Self::State> {
let mut ids = SmallVec::new(); let mut access = Access::new();
access.read_all_components();
B::get_component_ids(components, &mut |maybe_id| { B::get_component_ids(components, &mut |maybe_id| {
// If the component isn't registered, we don't have a `ComponentId`
// to use to exclude its access.
// Rather than fail, just try to take additional access.
// This is sound because access checks will run on the resulting access.
// Since the component isn't registered, there are no entities with that
// component, and the extra access will usually have no effect.
if let Some(id) = maybe_id { if let Some(id) = maybe_id {
ids.push(id); access.remove_component_read(id);
} }
}); });
Some(ids) Some(access)
} }
fn matches_component_set(_: &Self::State, _: &impl Fn(ComponentId) -> bool) -> bool { fn matches_component_set(_: &Self::State, _: &impl Fn(ComponentId) -> bool) -> bool {
@ -1241,13 +1240,13 @@ where
} }
/// SAFETY: `Self` is the same as `Self::ReadOnly`. /// SAFETY: `Self` is the same as `Self::ReadOnly`.
unsafe impl<'a, B> QueryData for EntityRefExcept<'a, B> unsafe impl<'a, 'b, B> QueryData for EntityRefExcept<'a, 'b, B>
where where
B: Bundle, B: Bundle,
{ {
const IS_READ_ONLY: bool = true; const IS_READ_ONLY: bool = true;
type ReadOnly = Self; type ReadOnly = Self;
type Item<'w, 's> = EntityRefExcept<'w, B>; type Item<'w, 's> = EntityRefExcept<'w, 's, B>;
fn shrink<'wlong: 'wshort, 'wshort, 's>( fn shrink<'wlong: 'wshort, 'wshort, 's>(
item: Self::Item<'wlong, 's>, item: Self::Item<'wlong, 's>,
@ -1256,7 +1255,7 @@ where
} }
unsafe fn fetch<'w, 's>( unsafe fn fetch<'w, 's>(
_state: &'s Self::State, access: &'s Self::State,
fetch: &mut Self::Fetch<'w>, fetch: &mut Self::Fetch<'w>,
entity: Entity, entity: Entity,
_: TableRow, _: TableRow,
@ -1265,23 +1264,23 @@ where
.world .world
.get_entity_with_ticks(entity, fetch.last_run, fetch.this_run) .get_entity_with_ticks(entity, fetch.last_run, fetch.this_run)
.unwrap(); .unwrap();
EntityRefExcept::new(cell) EntityRefExcept::new(cell, access)
} }
} }
/// SAFETY: `EntityRefExcept` enforces read-only access to its contained /// SAFETY: `EntityRefExcept` enforces read-only access to its contained
/// components. /// components.
unsafe impl<'a, B> ReadOnlyQueryData for EntityRefExcept<'a, B> where B: Bundle {} unsafe impl<B> ReadOnlyQueryData for EntityRefExcept<'_, '_, B> where B: Bundle {}
/// SAFETY: `EntityMutExcept` guards access to all components in the bundle `B` /// SAFETY: `EntityMutExcept` guards access to all components in the bundle `B`
/// and populates `Access` values so that queries that conflict with this access /// and populates `Access` values so that queries that conflict with this access
/// are rejected. /// are rejected.
unsafe impl<'a, B> WorldQuery for EntityMutExcept<'a, B> unsafe impl<'a, 'b, B> WorldQuery for EntityMutExcept<'a, 'b, B>
where where
B: Bundle, B: Bundle,
{ {
type Fetch<'w> = EntityFetch<'w>; type Fetch<'w> = EntityFetch<'w>;
type State = SmallVec<[ComponentId; 4]>; type State = Access<ComponentId>;
fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {
fetch fetch
@ -1316,33 +1315,39 @@ where
state: &Self::State, state: &Self::State,
filtered_access: &mut FilteredAccess<ComponentId>, filtered_access: &mut FilteredAccess<ComponentId>,
) { ) {
let mut my_access = Access::new();
my_access.write_all_components();
for id in state {
my_access.remove_component_read(*id);
}
let access = filtered_access.access_mut(); let access = filtered_access.access_mut();
assert!( assert!(
access.is_compatible(&my_access), access.is_compatible(state),
"`EntityMutExcept<{}>` conflicts with a previous access in this query.", "`EntityMutExcept<{}>` conflicts with a previous access in this query.",
DebugName::type_name::<B>() DebugName::type_name::<B>()
); );
access.extend(&my_access); access.extend(state);
} }
fn init_state(world: &mut World) -> Self::State { fn init_state(world: &mut World) -> Self::State {
Self::get_state(world.components()).unwrap() let mut access = Access::new();
access.write_all_components();
B::component_ids(&mut world.components_registrator(), &mut |id| {
access.remove_component_read(id);
});
access
} }
fn get_state(components: &Components) -> Option<Self::State> { fn get_state(components: &Components) -> Option<Self::State> {
let mut ids = SmallVec::new(); let mut access = Access::new();
access.write_all_components();
B::get_component_ids(components, &mut |maybe_id| { B::get_component_ids(components, &mut |maybe_id| {
// If the component isn't registered, we don't have a `ComponentId`
// to use to exclude its access.
// Rather than fail, just try to take additional access.
// This is sound because access checks will run on the resulting access.
// Since the component isn't registered, there are no entities with that
// component, and the extra access will usually have no effect.
if let Some(id) = maybe_id { if let Some(id) = maybe_id {
ids.push(id); access.remove_component_read(id);
} }
}); });
Some(ids) Some(access)
} }
fn matches_component_set(_: &Self::State, _: &impl Fn(ComponentId) -> bool) -> bool { fn matches_component_set(_: &Self::State, _: &impl Fn(ComponentId) -> bool) -> bool {
@ -1352,13 +1357,13 @@ where
/// SAFETY: All accesses that `EntityRefExcept` provides are also accesses that /// SAFETY: All accesses that `EntityRefExcept` provides are also accesses that
/// `EntityMutExcept` provides. /// `EntityMutExcept` provides.
unsafe impl<'a, B> QueryData for EntityMutExcept<'a, B> unsafe impl<'a, 'b, B> QueryData for EntityMutExcept<'a, 'b, B>
where where
B: Bundle, B: Bundle,
{ {
const IS_READ_ONLY: bool = false; const IS_READ_ONLY: bool = false;
type ReadOnly = EntityRefExcept<'a, B>; type ReadOnly = EntityRefExcept<'a, 'b, B>;
type Item<'w, 's> = EntityMutExcept<'w, B>; type Item<'w, 's> = EntityMutExcept<'w, 's, B>;
fn shrink<'wlong: 'wshort, 'wshort, 's>( fn shrink<'wlong: 'wshort, 'wshort, 's>(
item: Self::Item<'wlong, 's>, item: Self::Item<'wlong, 's>,
@ -1367,7 +1372,7 @@ where
} }
unsafe fn fetch<'w, 's>( unsafe fn fetch<'w, 's>(
_state: &'s Self::State, access: &'s Self::State,
fetch: &mut Self::Fetch<'w>, fetch: &mut Self::Fetch<'w>,
entity: Entity, entity: Entity,
_: TableRow, _: TableRow,
@ -1376,7 +1381,7 @@ where
.world .world
.get_entity_with_ticks(entity, fetch.last_run, fetch.this_run) .get_entity_with_ticks(entity, fetch.last_run, fetch.this_run)
.unwrap(); .unwrap();
EntityMutExcept::new(cell) EntityMutExcept::new(cell, access)
} }
} }

View File

@ -958,25 +958,25 @@ unsafe impl<'w, 's, F: QueryFilter> EntitySetIterator for QueryIter<'w, 's, Enti
// SAFETY: [`QueryIter`] is guaranteed to return every matching entity once and only once. // SAFETY: [`QueryIter`] is guaranteed to return every matching entity once and only once.
unsafe impl<'w, 's, F: QueryFilter> EntitySetIterator unsafe impl<'w, 's, F: QueryFilter> EntitySetIterator
for QueryIter<'w, 's, FilteredEntityRef<'_>, F> for QueryIter<'w, 's, FilteredEntityRef<'_, '_>, F>
{ {
} }
// SAFETY: [`QueryIter`] is guaranteed to return every matching entity once and only once. // SAFETY: [`QueryIter`] is guaranteed to return every matching entity once and only once.
unsafe impl<'w, 's, F: QueryFilter> EntitySetIterator unsafe impl<'w, 's, F: QueryFilter> EntitySetIterator
for QueryIter<'w, 's, FilteredEntityMut<'_>, F> for QueryIter<'w, 's, FilteredEntityMut<'_, '_>, F>
{ {
} }
// SAFETY: [`QueryIter`] is guaranteed to return every matching entity once and only once. // SAFETY: [`QueryIter`] is guaranteed to return every matching entity once and only once.
unsafe impl<'w, 's, F: QueryFilter, B: Bundle> EntitySetIterator unsafe impl<'w, 's, F: QueryFilter, B: Bundle> EntitySetIterator
for QueryIter<'w, 's, EntityRefExcept<'_, B>, F> for QueryIter<'w, 's, EntityRefExcept<'_, '_, B>, F>
{ {
} }
// SAFETY: [`QueryIter`] is guaranteed to return every matching entity once and only once. // SAFETY: [`QueryIter`] is guaranteed to return every matching entity once and only once.
unsafe impl<'w, 's, F: QueryFilter, B: Bundle> EntitySetIterator unsafe impl<'w, 's, F: QueryFilter, B: Bundle> EntitySetIterator
for QueryIter<'w, 's, EntityMutExcept<'_, B>, F> for QueryIter<'w, 's, EntityMutExcept<'_, '_, B>, F>
{ {
} }

View File

@ -118,9 +118,9 @@ pub struct ReflectComponentFns {
/// Function pointer implementing [`ReflectComponent::contains()`]. /// Function pointer implementing [`ReflectComponent::contains()`].
pub contains: fn(FilteredEntityRef) -> bool, pub contains: fn(FilteredEntityRef) -> bool,
/// Function pointer implementing [`ReflectComponent::reflect()`]. /// Function pointer implementing [`ReflectComponent::reflect()`].
pub reflect: fn(FilteredEntityRef) -> Option<&dyn Reflect>, pub reflect: for<'w> fn(FilteredEntityRef<'w, '_>) -> Option<&'w dyn Reflect>,
/// Function pointer implementing [`ReflectComponent::reflect_mut()`]. /// Function pointer implementing [`ReflectComponent::reflect_mut()`].
pub reflect_mut: fn(FilteredEntityMut) -> Option<Mut<dyn Reflect>>, pub reflect_mut: for<'w> fn(FilteredEntityMut<'w, '_>) -> Option<Mut<'w, dyn Reflect>>,
/// Function pointer implementing [`ReflectComponent::map_entities()`]. /// Function pointer implementing [`ReflectComponent::map_entities()`].
pub map_entities: fn(&mut dyn Reflect, &mut dyn EntityMapper), pub map_entities: fn(&mut dyn Reflect, &mut dyn EntityMapper),
/// Function pointer implementing [`ReflectComponent::reflect_unchecked_mut()`]. /// Function pointer implementing [`ReflectComponent::reflect_unchecked_mut()`].
@ -189,12 +189,15 @@ impl ReflectComponent {
} }
/// Returns whether entity contains this [`Component`] /// Returns whether entity contains this [`Component`]
pub fn contains<'a>(&self, entity: impl Into<FilteredEntityRef<'a>>) -> bool { pub fn contains<'w, 's>(&self, entity: impl Into<FilteredEntityRef<'w, 's>>) -> bool {
(self.0.contains)(entity.into()) (self.0.contains)(entity.into())
} }
/// Gets the value of this [`Component`] type from the entity as a reflected reference. /// Gets the value of this [`Component`] type from the entity as a reflected reference.
pub fn reflect<'a>(&self, entity: impl Into<FilteredEntityRef<'a>>) -> Option<&'a dyn Reflect> { pub fn reflect<'w, 's>(
&self,
entity: impl Into<FilteredEntityRef<'w, 's>>,
) -> Option<&'w dyn Reflect> {
(self.0.reflect)(entity.into()) (self.0.reflect)(entity.into())
} }
@ -203,10 +206,10 @@ impl ReflectComponent {
/// # Panics /// # Panics
/// ///
/// Panics if [`Component`] is immutable. /// Panics if [`Component`] is immutable.
pub fn reflect_mut<'a>( pub fn reflect_mut<'w, 's>(
&self, &self,
entity: impl Into<FilteredEntityMut<'a>>, entity: impl Into<FilteredEntityMut<'w, 's>>,
) -> Option<Mut<'a, dyn Reflect>> { ) -> Option<Mut<'w, dyn Reflect>> {
(self.0.reflect_mut)(entity.into()) (self.0.reflect_mut)(entity.into())
} }

View File

@ -339,10 +339,10 @@ impl<'a> From<&'a EntityMut<'_>> for EntityRef<'a> {
} }
} }
impl<'a> TryFrom<FilteredEntityRef<'a>> for EntityRef<'a> { impl<'a> TryFrom<FilteredEntityRef<'a, '_>> for EntityRef<'a> {
type Error = TryFromFilteredError; type Error = TryFromFilteredError;
fn try_from(entity: FilteredEntityRef<'a>) -> Result<Self, Self::Error> { fn try_from(entity: FilteredEntityRef<'a, '_>) -> Result<Self, Self::Error> {
if !entity.access.has_read_all() { if !entity.access.has_read_all() {
Err(TryFromFilteredError::MissingReadAllAccess) Err(TryFromFilteredError::MissingReadAllAccess)
} else { } else {
@ -352,10 +352,10 @@ impl<'a> TryFrom<FilteredEntityRef<'a>> for EntityRef<'a> {
} }
} }
impl<'a> TryFrom<&'a FilteredEntityRef<'_>> for EntityRef<'a> { impl<'a> TryFrom<&'a FilteredEntityRef<'_, '_>> for EntityRef<'a> {
type Error = TryFromFilteredError; type Error = TryFromFilteredError;
fn try_from(entity: &'a FilteredEntityRef<'_>) -> Result<Self, Self::Error> { fn try_from(entity: &'a FilteredEntityRef<'_, '_>) -> Result<Self, Self::Error> {
if !entity.access.has_read_all() { if !entity.access.has_read_all() {
Err(TryFromFilteredError::MissingReadAllAccess) Err(TryFromFilteredError::MissingReadAllAccess)
} else { } else {
@ -365,10 +365,10 @@ impl<'a> TryFrom<&'a FilteredEntityRef<'_>> for EntityRef<'a> {
} }
} }
impl<'a> TryFrom<FilteredEntityMut<'a>> for EntityRef<'a> { impl<'a> TryFrom<FilteredEntityMut<'a, '_>> for EntityRef<'a> {
type Error = TryFromFilteredError; type Error = TryFromFilteredError;
fn try_from(entity: FilteredEntityMut<'a>) -> Result<Self, Self::Error> { fn try_from(entity: FilteredEntityMut<'a, '_>) -> Result<Self, Self::Error> {
if !entity.access.has_read_all() { if !entity.access.has_read_all() {
Err(TryFromFilteredError::MissingReadAllAccess) Err(TryFromFilteredError::MissingReadAllAccess)
} else { } else {
@ -378,10 +378,10 @@ impl<'a> TryFrom<FilteredEntityMut<'a>> for EntityRef<'a> {
} }
} }
impl<'a> TryFrom<&'a FilteredEntityMut<'_>> for EntityRef<'a> { impl<'a> TryFrom<&'a FilteredEntityMut<'_, '_>> for EntityRef<'a> {
type Error = TryFromFilteredError; type Error = TryFromFilteredError;
fn try_from(entity: &'a FilteredEntityMut<'_>) -> Result<Self, Self::Error> { fn try_from(entity: &'a FilteredEntityMut<'_, '_>) -> Result<Self, Self::Error> {
if !entity.access.has_read_all() { if !entity.access.has_read_all() {
Err(TryFromFilteredError::MissingReadAllAccess) Err(TryFromFilteredError::MissingReadAllAccess)
} else { } else {
@ -1021,10 +1021,10 @@ impl<'a> From<&'a mut EntityWorldMut<'_>> for EntityMut<'a> {
} }
} }
impl<'a> TryFrom<FilteredEntityMut<'a>> for EntityMut<'a> { impl<'a> TryFrom<FilteredEntityMut<'a, '_>> for EntityMut<'a> {
type Error = TryFromFilteredError; type Error = TryFromFilteredError;
fn try_from(entity: FilteredEntityMut<'a>) -> Result<Self, Self::Error> { fn try_from(entity: FilteredEntityMut<'a, '_>) -> Result<Self, Self::Error> {
if !entity.access.has_read_all() { if !entity.access.has_read_all() {
Err(TryFromFilteredError::MissingReadAllAccess) Err(TryFromFilteredError::MissingReadAllAccess)
} else if !entity.access.has_write_all() { } else if !entity.access.has_write_all() {
@ -1036,10 +1036,10 @@ impl<'a> TryFrom<FilteredEntityMut<'a>> for EntityMut<'a> {
} }
} }
impl<'a> TryFrom<&'a mut FilteredEntityMut<'_>> for EntityMut<'a> { impl<'a> TryFrom<&'a mut FilteredEntityMut<'_, '_>> for EntityMut<'a> {
type Error = TryFromFilteredError; type Error = TryFromFilteredError;
fn try_from(entity: &'a mut FilteredEntityMut<'_>) -> Result<Self, Self::Error> { fn try_from(entity: &'a mut FilteredEntityMut<'_, '_>) -> Result<Self, Self::Error> {
if !entity.access.has_read_all() { if !entity.access.has_read_all() {
Err(TryFromFilteredError::MissingReadAllAccess) Err(TryFromFilteredError::MissingReadAllAccess)
} else if !entity.access.has_write_all() { } else if !entity.access.has_write_all() {
@ -3369,20 +3369,23 @@ impl<'w, 'a, T: Component> VacantComponentEntry<'w, 'a, T> {
/// let filtered_entity: FilteredEntityRef = query.single(&mut world).unwrap(); /// let filtered_entity: FilteredEntityRef = query.single(&mut world).unwrap();
/// let component: &A = filtered_entity.get().unwrap(); /// let component: &A = filtered_entity.get().unwrap();
/// ``` /// ```
#[derive(Clone)] #[derive(Clone, Copy)]
pub struct FilteredEntityRef<'w> { pub struct FilteredEntityRef<'w, 's> {
entity: UnsafeEntityCell<'w>, entity: UnsafeEntityCell<'w>,
access: Access<ComponentId>, access: &'s Access<ComponentId>,
} }
impl<'w> FilteredEntityRef<'w> { impl<'w, 's> FilteredEntityRef<'w, 's> {
/// # Safety /// # Safety
/// - No `&mut World` can exist from the underlying `UnsafeWorldCell` /// - No `&mut World` can exist from the underlying `UnsafeWorldCell`
/// - If `access` takes read access to a component no mutable reference to that /// - If `access` takes read access to a component no mutable reference to that
/// component can exist at the same time as the returned [`FilteredEntityMut`] /// component can exist at the same time as the returned [`FilteredEntityMut`]
/// - If `access` takes any access for a component `entity` must have that component. /// - If `access` takes any access for a component `entity` must have that component.
#[inline] #[inline]
pub(crate) unsafe fn new(entity: UnsafeEntityCell<'w>, access: Access<ComponentId>) -> Self { pub(crate) unsafe fn new(
entity: UnsafeEntityCell<'w>,
access: &'s Access<ComponentId>,
) -> Self {
Self { entity, access } Self { entity, access }
} }
@ -3408,7 +3411,7 @@ impl<'w> FilteredEntityRef<'w> {
/// Returns a reference to the underlying [`Access`]. /// Returns a reference to the underlying [`Access`].
#[inline] #[inline]
pub fn access(&self) -> &Access<ComponentId> { pub fn access(&self) -> &Access<ComponentId> {
&self.access self.access
} }
/// Returns `true` if the current entity has a component of type `T`. /// Returns `true` if the current entity has a component of type `T`.
@ -3541,123 +3544,99 @@ impl<'w> FilteredEntityRef<'w> {
} }
} }
impl<'w> From<FilteredEntityMut<'w>> for FilteredEntityRef<'w> { impl<'w, 's> From<FilteredEntityMut<'w, 's>> for FilteredEntityRef<'w, 's> {
#[inline] #[inline]
fn from(entity: FilteredEntityMut<'w>) -> Self { fn from(entity: FilteredEntityMut<'w, 's>) -> Self {
// SAFETY: // SAFETY:
// - `FilteredEntityMut` guarantees exclusive access to all components in the new `FilteredEntityRef`. // - `FilteredEntityMut` guarantees exclusive access to all components in the new `FilteredEntityRef`.
unsafe { FilteredEntityRef::new(entity.entity, entity.access) } unsafe { FilteredEntityRef::new(entity.entity, entity.access) }
} }
} }
impl<'a> From<&'a FilteredEntityMut<'_>> for FilteredEntityRef<'a> { impl<'w, 's> From<&'w FilteredEntityMut<'_, 's>> for FilteredEntityRef<'w, 's> {
#[inline] #[inline]
fn from(entity: &'a FilteredEntityMut<'_>) -> Self { fn from(entity: &'w FilteredEntityMut<'_, 's>) -> Self {
// SAFETY: // SAFETY:
// - `FilteredEntityMut` guarantees exclusive access to all components in the new `FilteredEntityRef`. // - `FilteredEntityMut` guarantees exclusive access to all components in the new `FilteredEntityRef`.
unsafe { FilteredEntityRef::new(entity.entity, entity.access.clone()) } unsafe { FilteredEntityRef::new(entity.entity, entity.access) }
} }
} }
impl<'a> From<EntityRef<'a>> for FilteredEntityRef<'a> { impl<'a> From<EntityRef<'a>> for FilteredEntityRef<'a, 'static> {
fn from(entity: EntityRef<'a>) -> Self { fn from(entity: EntityRef<'a>) -> Self {
// SAFETY: // SAFETY:
// - `EntityRef` guarantees exclusive access to all components in the new `FilteredEntityRef`. // - `EntityRef` guarantees exclusive access to all components in the new `FilteredEntityRef`.
unsafe { unsafe { FilteredEntityRef::new(entity.cell, const { &Access::new_read_all() }) }
let mut access = Access::default();
access.read_all();
FilteredEntityRef::new(entity.cell, access)
}
} }
} }
impl<'a> From<&'a EntityRef<'_>> for FilteredEntityRef<'a> { impl<'a> From<&'a EntityRef<'_>> for FilteredEntityRef<'a, 'static> {
fn from(entity: &'a EntityRef<'_>) -> Self { fn from(entity: &'a EntityRef<'_>) -> Self {
// SAFETY: // SAFETY:
// - `EntityRef` guarantees exclusive access to all components in the new `FilteredEntityRef`. // - `EntityRef` guarantees exclusive access to all components in the new `FilteredEntityRef`.
unsafe { unsafe { FilteredEntityRef::new(entity.cell, const { &Access::new_read_all() }) }
let mut access = Access::default();
access.read_all();
FilteredEntityRef::new(entity.cell, access)
}
} }
} }
impl<'a> From<EntityMut<'a>> for FilteredEntityRef<'a> { impl<'a> From<EntityMut<'a>> for FilteredEntityRef<'a, 'static> {
fn from(entity: EntityMut<'a>) -> Self { fn from(entity: EntityMut<'a>) -> Self {
// SAFETY: // SAFETY:
// - `EntityMut` guarantees exclusive access to all components in the new `FilteredEntityRef`. // - `EntityMut` guarantees exclusive access to all components in the new `FilteredEntityRef`.
unsafe { unsafe { FilteredEntityRef::new(entity.cell, const { &Access::new_read_all() }) }
let mut access = Access::default();
access.read_all();
FilteredEntityRef::new(entity.cell, access)
}
} }
} }
impl<'a> From<&'a EntityMut<'_>> for FilteredEntityRef<'a> { impl<'a> From<&'a EntityMut<'_>> for FilteredEntityRef<'a, 'static> {
fn from(entity: &'a EntityMut<'_>) -> Self { fn from(entity: &'a EntityMut<'_>) -> Self {
// SAFETY: // SAFETY:
// - `EntityMut` guarantees exclusive access to all components in the new `FilteredEntityRef`. // - `EntityMut` guarantees exclusive access to all components in the new `FilteredEntityRef`.
unsafe { unsafe { FilteredEntityRef::new(entity.cell, const { &Access::new_read_all() }) }
let mut access = Access::default();
access.read_all();
FilteredEntityRef::new(entity.cell, access)
}
} }
} }
impl<'a> From<EntityWorldMut<'a>> for FilteredEntityRef<'a> { impl<'a> From<EntityWorldMut<'a>> for FilteredEntityRef<'a, 'static> {
fn from(entity: EntityWorldMut<'a>) -> Self { fn from(entity: EntityWorldMut<'a>) -> Self {
// SAFETY: // SAFETY:
// - `EntityWorldMut` guarantees exclusive access to the entire world. // - `EntityWorldMut` guarantees exclusive access to the entire world.
unsafe { unsafe {
let mut access = Access::default(); FilteredEntityRef::new(
access.read_all(); entity.into_unsafe_entity_cell(),
FilteredEntityRef::new(entity.into_unsafe_entity_cell(), access) const { &Access::new_read_all() },
)
} }
} }
} }
impl<'a> From<&'a EntityWorldMut<'_>> for FilteredEntityRef<'a> { impl<'a> From<&'a EntityWorldMut<'_>> for FilteredEntityRef<'a, 'static> {
fn from(entity: &'a EntityWorldMut<'_>) -> Self { fn from(entity: &'a EntityWorldMut<'_>) -> Self {
// SAFETY: // SAFETY:
// - `EntityWorldMut` guarantees exclusive access to the entire world. // - `EntityWorldMut` guarantees exclusive access to the entire world.
unsafe { unsafe {
let mut access = Access::default(); FilteredEntityRef::new(
access.read_all(); entity.as_unsafe_entity_cell_readonly(),
FilteredEntityRef::new(entity.as_unsafe_entity_cell_readonly(), access) const { &Access::new_read_all() },
)
} }
} }
} }
impl<'a, B: Bundle> From<&'a EntityRefExcept<'_, B>> for FilteredEntityRef<'a> { impl<'w, 's, B: Bundle> From<&'w EntityRefExcept<'_, 's, B>> for FilteredEntityRef<'w, 's> {
fn from(value: &'a EntityRefExcept<'_, B>) -> Self { fn from(value: &'w EntityRefExcept<'_, 's, B>) -> Self {
// SAFETY: // SAFETY:
// - The FilteredEntityRef has the same component access as the given EntityRefExcept. // - The FilteredEntityRef has the same component access as the given EntityRefExcept.
unsafe { unsafe { FilteredEntityRef::new(value.entity, value.access) }
let mut access = Access::default();
access.read_all();
let components = value.entity.world().components();
B::get_component_ids(components, &mut |maybe_id| {
if let Some(id) = maybe_id {
access.remove_component_read(id);
}
});
FilteredEntityRef::new(value.entity, access)
}
} }
} }
impl PartialEq for FilteredEntityRef<'_> { impl PartialEq for FilteredEntityRef<'_, '_> {
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
self.entity() == other.entity() self.entity() == other.entity()
} }
} }
impl Eq for FilteredEntityRef<'_> {} impl Eq for FilteredEntityRef<'_, '_> {}
impl PartialOrd for FilteredEntityRef<'_> { impl PartialOrd for FilteredEntityRef<'_, '_> {
/// [`FilteredEntityRef`]'s comparison trait implementations match the underlying [`Entity`], /// [`FilteredEntityRef`]'s comparison trait implementations match the underlying [`Entity`],
/// and cannot discern between different worlds. /// and cannot discern between different worlds.
fn partial_cmp(&self, other: &Self) -> Option<Ordering> { fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
@ -3665,26 +3644,26 @@ impl PartialOrd for FilteredEntityRef<'_> {
} }
} }
impl Ord for FilteredEntityRef<'_> { impl Ord for FilteredEntityRef<'_, '_> {
fn cmp(&self, other: &Self) -> Ordering { fn cmp(&self, other: &Self) -> Ordering {
self.entity().cmp(&other.entity()) self.entity().cmp(&other.entity())
} }
} }
impl Hash for FilteredEntityRef<'_> { impl Hash for FilteredEntityRef<'_, '_> {
fn hash<H: Hasher>(&self, state: &mut H) { fn hash<H: Hasher>(&self, state: &mut H) {
self.entity().hash(state); self.entity().hash(state);
} }
} }
impl ContainsEntity for FilteredEntityRef<'_> { impl ContainsEntity for FilteredEntityRef<'_, '_> {
fn entity(&self) -> Entity { fn entity(&self) -> Entity {
self.id() self.id()
} }
} }
// SAFETY: This type represents one Entity. We implement the comparison traits based on that Entity. // SAFETY: This type represents one Entity. We implement the comparison traits based on that Entity.
unsafe impl EntityEquivalent for FilteredEntityRef<'_> {} unsafe impl EntityEquivalent for FilteredEntityRef<'_, '_> {}
/// Provides mutable access to a single entity and some of its components defined by the contained [`Access`]. /// Provides mutable access to a single entity and some of its components defined by the contained [`Access`].
/// ///
@ -3709,12 +3688,12 @@ unsafe impl EntityEquivalent for FilteredEntityRef<'_> {}
/// let mut filtered_entity: FilteredEntityMut = query.single_mut(&mut world).unwrap(); /// let mut filtered_entity: FilteredEntityMut = query.single_mut(&mut world).unwrap();
/// let component: Mut<A> = filtered_entity.get_mut().unwrap(); /// let component: Mut<A> = filtered_entity.get_mut().unwrap();
/// ``` /// ```
pub struct FilteredEntityMut<'w> { pub struct FilteredEntityMut<'w, 's> {
entity: UnsafeEntityCell<'w>, entity: UnsafeEntityCell<'w>,
access: Access<ComponentId>, access: &'s Access<ComponentId>,
} }
impl<'w> FilteredEntityMut<'w> { impl<'w, 's> FilteredEntityMut<'w, 's> {
/// # Safety /// # Safety
/// - No `&mut World` can exist from the underlying `UnsafeWorldCell` /// - No `&mut World` can exist from the underlying `UnsafeWorldCell`
/// - If `access` takes read access to a component no mutable reference to that /// - If `access` takes read access to a component no mutable reference to that
@ -3723,20 +3702,23 @@ impl<'w> FilteredEntityMut<'w> {
/// may exist at the same time as the returned [`FilteredEntityMut`] /// may exist at the same time as the returned [`FilteredEntityMut`]
/// - If `access` takes any access for a component `entity` must have that component. /// - If `access` takes any access for a component `entity` must have that component.
#[inline] #[inline]
pub(crate) unsafe fn new(entity: UnsafeEntityCell<'w>, access: Access<ComponentId>) -> Self { pub(crate) unsafe fn new(
entity: UnsafeEntityCell<'w>,
access: &'s Access<ComponentId>,
) -> Self {
Self { entity, access } Self { entity, access }
} }
/// Returns a new instance with a shorter lifetime. /// Returns a new instance with a shorter lifetime.
/// This is useful if you have `&mut FilteredEntityMut`, but you need `FilteredEntityMut`. /// This is useful if you have `&mut FilteredEntityMut`, but you need `FilteredEntityMut`.
pub fn reborrow(&mut self) -> FilteredEntityMut<'_> { pub fn reborrow(&mut self) -> FilteredEntityMut<'_, 's> {
// SAFETY: We have exclusive access to the entire entity and its components. // SAFETY: We have exclusive access to the entire entity and its components.
unsafe { Self::new(self.entity, self.access.clone()) } unsafe { Self::new(self.entity, self.access) }
} }
/// Gets read-only access to all of the entity's components. /// Gets read-only access to all of the entity's components.
#[inline] #[inline]
pub fn as_readonly(&self) -> FilteredEntityRef<'_> { pub fn as_readonly(&self) -> FilteredEntityRef<'_, 's> {
FilteredEntityRef::from(self) FilteredEntityRef::from(self)
} }
@ -3762,7 +3744,7 @@ impl<'w> FilteredEntityMut<'w> {
/// Returns a reference to the underlying [`Access`]. /// Returns a reference to the underlying [`Access`].
#[inline] #[inline]
pub fn access(&self) -> &Access<ComponentId> { pub fn access(&self) -> &Access<ComponentId> {
&self.access self.access
} }
/// Returns `true` if the current entity has a component of type `T`. /// Returns `true` if the current entity has a component of type `T`.
@ -3927,85 +3909,65 @@ impl<'w> FilteredEntityMut<'w> {
} }
} }
impl<'a> From<EntityMut<'a>> for FilteredEntityMut<'a> { impl<'a> From<EntityMut<'a>> for FilteredEntityMut<'a, 'static> {
fn from(entity: EntityMut<'a>) -> Self { fn from(entity: EntityMut<'a>) -> Self {
// SAFETY: // SAFETY:
// - `EntityMut` guarantees exclusive access to all components in the new `FilteredEntityMut`. // - `EntityMut` guarantees exclusive access to all components in the new `FilteredEntityMut`.
unsafe { unsafe { FilteredEntityMut::new(entity.cell, const { &Access::new_write_all() }) }
let mut access = Access::default();
access.read_all();
access.write_all();
FilteredEntityMut::new(entity.cell, access)
}
} }
} }
impl<'a> From<&'a mut EntityMut<'_>> for FilteredEntityMut<'a> { impl<'a> From<&'a mut EntityMut<'_>> for FilteredEntityMut<'a, 'static> {
fn from(entity: &'a mut EntityMut<'_>) -> Self { fn from(entity: &'a mut EntityMut<'_>) -> Self {
// SAFETY: // SAFETY:
// - `EntityMut` guarantees exclusive access to all components in the new `FilteredEntityMut`. // - `EntityMut` guarantees exclusive access to all components in the new `FilteredEntityMut`.
unsafe { unsafe { FilteredEntityMut::new(entity.cell, const { &Access::new_write_all() }) }
let mut access = Access::default();
access.read_all();
access.write_all();
FilteredEntityMut::new(entity.cell, access)
}
} }
} }
impl<'a> From<EntityWorldMut<'a>> for FilteredEntityMut<'a> { impl<'a> From<EntityWorldMut<'a>> for FilteredEntityMut<'a, 'static> {
fn from(entity: EntityWorldMut<'a>) -> Self { fn from(entity: EntityWorldMut<'a>) -> Self {
// SAFETY: // SAFETY:
// - `EntityWorldMut` guarantees exclusive access to the entire world. // - `EntityWorldMut` guarantees exclusive access to the entire world.
unsafe { unsafe {
let mut access = Access::default(); FilteredEntityMut::new(
access.read_all(); entity.into_unsafe_entity_cell(),
access.write_all(); const { &Access::new_write_all() },
FilteredEntityMut::new(entity.into_unsafe_entity_cell(), access) )
} }
} }
} }
impl<'a> From<&'a mut EntityWorldMut<'_>> for FilteredEntityMut<'a> { impl<'a> From<&'a mut EntityWorldMut<'_>> for FilteredEntityMut<'a, 'static> {
fn from(entity: &'a mut EntityWorldMut<'_>) -> Self { fn from(entity: &'a mut EntityWorldMut<'_>) -> Self {
// SAFETY: // SAFETY:
// - `EntityWorldMut` guarantees exclusive access to the entire world. // - `EntityWorldMut` guarantees exclusive access to the entire world.
unsafe { unsafe {
let mut access = Access::default(); FilteredEntityMut::new(
access.read_all(); entity.as_unsafe_entity_cell(),
access.write_all(); const { &Access::new_write_all() },
FilteredEntityMut::new(entity.as_unsafe_entity_cell(), access) )
} }
} }
} }
impl<'a, B: Bundle> From<&'a EntityMutExcept<'_, B>> for FilteredEntityMut<'a> { impl<'w, 's, B: Bundle> From<&'w EntityMutExcept<'_, 's, B>> for FilteredEntityMut<'w, 's> {
fn from(value: &'a EntityMutExcept<'_, B>) -> Self { fn from(value: &'w EntityMutExcept<'_, 's, B>) -> Self {
// SAFETY: // SAFETY:
// - The FilteredEntityMut has the same component access as the given EntityMutExcept. // - The FilteredEntityMut has the same component access as the given EntityMutExcept.
unsafe { unsafe { FilteredEntityMut::new(value.entity, value.access) }
let mut access = Access::default();
access.write_all();
let components = value.entity.world().components();
B::get_component_ids(components, &mut |maybe_id| {
if let Some(id) = maybe_id {
access.remove_component_read(id);
}
});
FilteredEntityMut::new(value.entity, access)
}
} }
} }
impl PartialEq for FilteredEntityMut<'_> { impl PartialEq for FilteredEntityMut<'_, '_> {
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
self.entity() == other.entity() self.entity() == other.entity()
} }
} }
impl Eq for FilteredEntityMut<'_> {} impl Eq for FilteredEntityMut<'_, '_> {}
impl PartialOrd for FilteredEntityMut<'_> { impl PartialOrd for FilteredEntityMut<'_, '_> {
/// [`FilteredEntityMut`]'s comparison trait implementations match the underlying [`Entity`], /// [`FilteredEntityMut`]'s comparison trait implementations match the underlying [`Entity`],
/// and cannot discern between different worlds. /// and cannot discern between different worlds.
fn partial_cmp(&self, other: &Self) -> Option<Ordering> { fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
@ -4013,26 +3975,26 @@ impl PartialOrd for FilteredEntityMut<'_> {
} }
} }
impl Ord for FilteredEntityMut<'_> { impl Ord for FilteredEntityMut<'_, '_> {
fn cmp(&self, other: &Self) -> Ordering { fn cmp(&self, other: &Self) -> Ordering {
self.entity().cmp(&other.entity()) self.entity().cmp(&other.entity())
} }
} }
impl Hash for FilteredEntityMut<'_> { impl Hash for FilteredEntityMut<'_, '_> {
fn hash<H: Hasher>(&self, state: &mut H) { fn hash<H: Hasher>(&self, state: &mut H) {
self.entity().hash(state); self.entity().hash(state);
} }
} }
impl ContainsEntity for FilteredEntityMut<'_> { impl ContainsEntity for FilteredEntityMut<'_, '_> {
fn entity(&self) -> Entity { fn entity(&self) -> Entity {
self.id() self.id()
} }
} }
// SAFETY: This type represents one Entity. We implement the comparison traits based on that Entity. // SAFETY: This type represents one Entity. We implement the comparison traits based on that Entity.
unsafe impl EntityEquivalent for FilteredEntityMut<'_> {} unsafe impl EntityEquivalent for FilteredEntityMut<'_, '_> {}
/// Error type returned by [`TryFrom`] conversions from filtered entity types /// Error type returned by [`TryFrom`] conversions from filtered entity types
/// ([`FilteredEntityRef`]/[`FilteredEntityMut`]) to full-access entity types /// ([`FilteredEntityRef`]/[`FilteredEntityMut`]) to full-access entity types
@ -4051,23 +4013,28 @@ pub enum TryFromFilteredError {
/// Provides read-only access to a single entity and all its components, save /// Provides read-only access to a single entity and all its components, save
/// for an explicitly-enumerated set. /// for an explicitly-enumerated set.
pub struct EntityRefExcept<'w, B> pub struct EntityRefExcept<'w, 's, B>
where where
B: Bundle, B: Bundle,
{ {
entity: UnsafeEntityCell<'w>, entity: UnsafeEntityCell<'w>,
access: &'s Access<ComponentId>,
phantom: PhantomData<B>, phantom: PhantomData<B>,
} }
impl<'w, B> EntityRefExcept<'w, B> impl<'w, 's, B> EntityRefExcept<'w, 's, B>
where where
B: Bundle, B: Bundle,
{ {
/// # Safety /// # Safety
/// Other users of `UnsafeEntityCell` must only have mutable access to the components in `B`. /// Other users of `UnsafeEntityCell` must only have mutable access to the components in `B`.
pub(crate) unsafe fn new(entity: UnsafeEntityCell<'w>) -> Self { pub(crate) unsafe fn new(
entity: UnsafeEntityCell<'w>,
access: &'s Access<ComponentId>,
) -> Self {
Self { Self {
entity, entity,
access,
phantom: PhantomData, phantom: PhantomData,
} }
} }
@ -4220,34 +4187,34 @@ where
} }
} }
impl<'a, B> From<&'a EntityMutExcept<'_, B>> for EntityRefExcept<'a, B> impl<'w, 's, B> From<&'w EntityMutExcept<'_, 's, B>> for EntityRefExcept<'w, 's, B>
where where
B: Bundle, B: Bundle,
{ {
fn from(entity: &'a EntityMutExcept<'_, B>) -> Self { fn from(entity: &'w EntityMutExcept<'_, 's, B>) -> Self {
// SAFETY: All accesses that `EntityRefExcept` provides are also // SAFETY: All accesses that `EntityRefExcept` provides are also
// accesses that `EntityMutExcept` provides. // accesses that `EntityMutExcept` provides.
unsafe { EntityRefExcept::new(entity.entity) } unsafe { EntityRefExcept::new(entity.entity, entity.access) }
} }
} }
impl<B: Bundle> Clone for EntityRefExcept<'_, B> { impl<B: Bundle> Clone for EntityRefExcept<'_, '_, B> {
fn clone(&self) -> Self { fn clone(&self) -> Self {
*self *self
} }
} }
impl<B: Bundle> Copy for EntityRefExcept<'_, B> {} impl<B: Bundle> Copy for EntityRefExcept<'_, '_, B> {}
impl<B: Bundle> PartialEq for EntityRefExcept<'_, B> { impl<B: Bundle> PartialEq for EntityRefExcept<'_, '_, B> {
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
self.entity() == other.entity() self.entity() == other.entity()
} }
} }
impl<B: Bundle> Eq for EntityRefExcept<'_, B> {} impl<B: Bundle> Eq for EntityRefExcept<'_, '_, B> {}
impl<B: Bundle> PartialOrd for EntityRefExcept<'_, B> { impl<B: Bundle> PartialOrd for EntityRefExcept<'_, '_, B> {
/// [`EntityRefExcept`]'s comparison trait implementations match the underlying [`Entity`], /// [`EntityRefExcept`]'s comparison trait implementations match the underlying [`Entity`],
/// and cannot discern between different worlds. /// and cannot discern between different worlds.
fn partial_cmp(&self, other: &Self) -> Option<Ordering> { fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
@ -4255,26 +4222,26 @@ impl<B: Bundle> PartialOrd for EntityRefExcept<'_, B> {
} }
} }
impl<B: Bundle> Ord for EntityRefExcept<'_, B> { impl<B: Bundle> Ord for EntityRefExcept<'_, '_, B> {
fn cmp(&self, other: &Self) -> Ordering { fn cmp(&self, other: &Self) -> Ordering {
self.entity().cmp(&other.entity()) self.entity().cmp(&other.entity())
} }
} }
impl<B: Bundle> Hash for EntityRefExcept<'_, B> { impl<B: Bundle> Hash for EntityRefExcept<'_, '_, B> {
fn hash<H: Hasher>(&self, state: &mut H) { fn hash<H: Hasher>(&self, state: &mut H) {
self.entity().hash(state); self.entity().hash(state);
} }
} }
impl<B: Bundle> ContainsEntity for EntityRefExcept<'_, B> { impl<B: Bundle> ContainsEntity for EntityRefExcept<'_, '_, B> {
fn entity(&self) -> Entity { fn entity(&self) -> Entity {
self.id() self.id()
} }
} }
// SAFETY: This type represents one Entity. We implement the comparison traits based on that Entity. // SAFETY: This type represents one Entity. We implement the comparison traits based on that Entity.
unsafe impl<B: Bundle> EntityEquivalent for EntityRefExcept<'_, B> {} unsafe impl<B: Bundle> EntityEquivalent for EntityRefExcept<'_, '_, B> {}
/// Provides mutable access to all components of an entity, with the exception /// Provides mutable access to all components of an entity, with the exception
/// of an explicit set. /// of an explicit set.
@ -4284,23 +4251,28 @@ unsafe impl<B: Bundle> EntityEquivalent for EntityRefExcept<'_, B> {}
/// queries that might match entities that this query also matches. If you don't /// queries that might match entities that this query also matches. If you don't
/// need access to all components, prefer a standard query with a /// need access to all components, prefer a standard query with a
/// [`crate::query::Without`] filter. /// [`crate::query::Without`] filter.
pub struct EntityMutExcept<'w, B> pub struct EntityMutExcept<'w, 's, B>
where where
B: Bundle, B: Bundle,
{ {
entity: UnsafeEntityCell<'w>, entity: UnsafeEntityCell<'w>,
access: &'s Access<ComponentId>,
phantom: PhantomData<B>, phantom: PhantomData<B>,
} }
impl<'w, B> EntityMutExcept<'w, B> impl<'w, 's, B> EntityMutExcept<'w, 's, B>
where where
B: Bundle, B: Bundle,
{ {
/// # Safety /// # Safety
/// Other users of `UnsafeEntityCell` must not have access to any components not in `B`. /// Other users of `UnsafeEntityCell` must not have access to any components not in `B`.
pub(crate) unsafe fn new(entity: UnsafeEntityCell<'w>) -> Self { pub(crate) unsafe fn new(
entity: UnsafeEntityCell<'w>,
access: &'s Access<ComponentId>,
) -> Self {
Self { Self {
entity, entity,
access,
phantom: PhantomData, phantom: PhantomData,
} }
} }
@ -4316,16 +4288,16 @@ where
/// ///
/// This is useful if you have `&mut EntityMutExcept`, but you need /// This is useful if you have `&mut EntityMutExcept`, but you need
/// `EntityMutExcept`. /// `EntityMutExcept`.
pub fn reborrow(&mut self) -> EntityMutExcept<'_, B> { pub fn reborrow(&mut self) -> EntityMutExcept<'_, 's, B> {
// SAFETY: We have exclusive access to the entire entity and the // SAFETY: We have exclusive access to the entire entity and the
// applicable components. // applicable components.
unsafe { Self::new(self.entity) } unsafe { Self::new(self.entity, self.access) }
} }
/// Gets read-only access to all of the entity's components, except for the /// Gets read-only access to all of the entity's components, except for the
/// ones in `CL`. /// ones in `CL`.
#[inline] #[inline]
pub fn as_readonly(&self) -> EntityRefExcept<'_, B> { pub fn as_readonly(&self) -> EntityRefExcept<'_, 's, B> {
EntityRefExcept::from(self) EntityRefExcept::from(self)
} }
@ -4454,15 +4426,15 @@ where
} }
} }
impl<B: Bundle> PartialEq for EntityMutExcept<'_, B> { impl<B: Bundle> PartialEq for EntityMutExcept<'_, '_, B> {
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
self.entity() == other.entity() self.entity() == other.entity()
} }
} }
impl<B: Bundle> Eq for EntityMutExcept<'_, B> {} impl<B: Bundle> Eq for EntityMutExcept<'_, '_, B> {}
impl<B: Bundle> PartialOrd for EntityMutExcept<'_, B> { impl<B: Bundle> PartialOrd for EntityMutExcept<'_, '_, B> {
/// [`EntityMutExcept`]'s comparison trait implementations match the underlying [`Entity`], /// [`EntityMutExcept`]'s comparison trait implementations match the underlying [`Entity`],
/// and cannot discern between different worlds. /// and cannot discern between different worlds.
fn partial_cmp(&self, other: &Self) -> Option<Ordering> { fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
@ -4470,26 +4442,26 @@ impl<B: Bundle> PartialOrd for EntityMutExcept<'_, B> {
} }
} }
impl<B: Bundle> Ord for EntityMutExcept<'_, B> { impl<B: Bundle> Ord for EntityMutExcept<'_, '_, B> {
fn cmp(&self, other: &Self) -> Ordering { fn cmp(&self, other: &Self) -> Ordering {
self.entity().cmp(&other.entity()) self.entity().cmp(&other.entity())
} }
} }
impl<B: Bundle> Hash for EntityMutExcept<'_, B> { impl<B: Bundle> Hash for EntityMutExcept<'_, '_, B> {
fn hash<H: Hasher>(&self, state: &mut H) { fn hash<H: Hasher>(&self, state: &mut H) {
self.entity().hash(state); self.entity().hash(state);
} }
} }
impl<B: Bundle> ContainsEntity for EntityMutExcept<'_, B> { impl<B: Bundle> ContainsEntity for EntityMutExcept<'_, '_, B> {
fn entity(&self) -> Entity { fn entity(&self) -> Entity {
self.id() self.id()
} }
} }
// SAFETY: This type represents one Entity. We implement the comparison traits based on that Entity. // SAFETY: This type represents one Entity. We implement the comparison traits based on that Entity.
unsafe impl<B: Bundle> EntityEquivalent for EntityMutExcept<'_, B> {} unsafe impl<B: Bundle> EntityEquivalent for EntityMutExcept<'_, '_, B> {}
fn bundle_contains_component<B>(components: &Components, query_id: ComponentId) -> bool fn bundle_contains_component<B>(components: &Components, query_id: ComponentId) -> bool
where where
@ -5523,6 +5495,19 @@ mod tests {
} }
} }
#[test]
fn entity_mut_except_registers_components() {
// Checks for a bug where `EntityMutExcept` would not register the component and
// would therefore not include an exception, causing it to conflict with the later query.
fn system1(_query: Query<EntityMutExcept<TestComponent>>, _: Query<&mut TestComponent>) {}
let mut world = World::new();
world.run_system_once(system1).unwrap();
fn system2(_: Query<&mut TestComponent>, _query: Query<EntityMutExcept<TestComponent>>) {}
let mut world = World::new();
world.run_system_once(system2).unwrap();
}
#[derive(Component)] #[derive(Component)]
struct A; struct A;

View File

@ -880,7 +880,7 @@ pub fn process_remote_query_request(In(params): In<Option<Value>>, world: &mut W
// The map of boolean-valued component presences: // The map of boolean-valued component presences:
let has_map = build_has_map( let has_map = build_has_map(
row.clone(), row,
has_paths_and_reflect_components.iter().copied(), has_paths_and_reflect_components.iter().copied(),
&unregistered_in_has, &unregistered_in_has,
); );
@ -1466,7 +1466,7 @@ fn build_has_map<'a>(
let mut has_map = <HashMap<_, _>>::default(); let mut has_map = <HashMap<_, _>>::default();
for (type_path, reflect_component) in paths_and_reflect_components { for (type_path, reflect_component) in paths_and_reflect_components {
let has = reflect_component.contains(entity_ref.clone()); let has = reflect_component.contains(entity_ref);
has_map.insert(type_path.to_owned(), Value::Bool(has)); has_map.insert(type_path.to_owned(), Value::Bool(has));
} }
unregistered_components.iter().for_each(|component| { unregistered_components.iter().for_each(|component| {