Add EntityDoesNotExistError, replace cases of Entity as an error, do some easy Resultification (#17855)
## Objective There's no general error for when an entity doesn't exist, and some methods are going to need one when they get Resultified. The closest thing is `EntityFetchError`, but that error has a slightly more specific purpose. ## Solution - Added `EntityDoesNotExistError`. - Contains `Entity` and `EntityDoesNotExistDetails`. - Changed `EntityFetchError` and `QueryEntityError`: - Changed `NoSuchEntity` variant to wrap `EntityDoesNotExistError` and renamed the variant to `EntityDoesNotExist`. - Renamed `EntityFetchError` to `EntityMutableFetchError` to make its purpose clearer. - Renamed `TryDespawnError` to `EntityDespawnError` to make it more general. - Changed `World::inspect_entity` to return `Result<[ok], EntityDoesNotExistError>` instead of panicking. - Changed `World::get_entity` and `WorldEntityFetch::fetch_ref` to return `Result<[ok], EntityDoesNotExistError>` instead of `Result<[ok], Entity>`. - Changed `UnsafeWorldCell::get_entity` to return `Result<UnsafeEntityCell, EntityDoesNotExistError>` instead of `Option<UnsafeEntityCell>`. ## Migration Guide - `World::inspect_entity` now returns `Result<impl Iterator<Item = &ComponentInfo>, EntityDoesNotExistError>` instead of `impl Iterator<Item = &ComponentInfo>`. - `World::get_entity` now returns `EntityDoesNotExistError` as an error instead of `Entity`. You can still access the entity's ID through the error's `entity` field. - `UnsafeWorldCell::get_entity` now returns `Result<UnsafeEntityCell, EntityDoesNotExistError>` instead of `Option<UnsafeEntityCell>`.
This commit is contained in:
parent
e186c7ccf4
commit
ee44560523
@ -1013,13 +1013,32 @@ impl Entities {
|
|||||||
.map(Option::flatten)
|
.map(Option::flatten)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Constructs a message explaining why an entity does not exists, if known.
|
/// Constructs a message explaining why an entity does not exist, if known.
|
||||||
pub(crate) fn entity_does_not_exist_error_details(
|
pub(crate) fn entity_does_not_exist_error_details(
|
||||||
&self,
|
&self,
|
||||||
_entity: Entity,
|
entity: Entity,
|
||||||
) -> EntityDoesNotExistDetails {
|
) -> EntityDoesNotExistDetails {
|
||||||
EntityDoesNotExistDetails {
|
EntityDoesNotExistDetails {
|
||||||
location: self.entity_get_spawned_or_despawned_by(_entity),
|
location: self.entity_get_spawned_or_despawned_by(entity),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An error that occurs when a specified [`Entity`] does not exist.
|
||||||
|
#[derive(thiserror::Error, Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
#[error("The entity with ID {entity} {details}")]
|
||||||
|
pub struct EntityDoesNotExistError {
|
||||||
|
/// The entity's ID.
|
||||||
|
pub entity: Entity,
|
||||||
|
/// Details on why the entity does not exist, if available.
|
||||||
|
pub details: EntityDoesNotExistDetails,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EntityDoesNotExistError {
|
||||||
|
pub(crate) fn new(entity: Entity, entities: &Entities) -> Self {
|
||||||
|
Self {
|
||||||
|
entity,
|
||||||
|
details: entities.entity_does_not_exist_error_details(entity),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
entity::{Entity, EntityDoesNotExistDetails},
|
entity::{Entity, EntityDoesNotExistError},
|
||||||
world::unsafe_world_cell::UnsafeWorldCell,
|
world::unsafe_world_cell::UnsafeWorldCell,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -14,13 +14,19 @@ pub enum QueryEntityError<'w> {
|
|||||||
/// Either it does not have a requested component, or it has a component which the query filters out.
|
/// Either it does not have a requested component, or it has a component which the query filters out.
|
||||||
QueryDoesNotMatch(Entity, UnsafeWorldCell<'w>),
|
QueryDoesNotMatch(Entity, UnsafeWorldCell<'w>),
|
||||||
/// The given [`Entity`] does not exist.
|
/// The given [`Entity`] does not exist.
|
||||||
NoSuchEntity(Entity, EntityDoesNotExistDetails),
|
EntityDoesNotExist(EntityDoesNotExistError),
|
||||||
/// The [`Entity`] was requested mutably more than once.
|
/// The [`Entity`] was requested mutably more than once.
|
||||||
///
|
///
|
||||||
/// See [`Query::get_many_mut`](crate::system::Query::get_many_mut) for an example.
|
/// See [`Query::get_many_mut`](crate::system::Query::get_many_mut) for an example.
|
||||||
AliasedMutability(Entity),
|
AliasedMutability(Entity),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'w> From<EntityDoesNotExistError> for QueryEntityError<'w> {
|
||||||
|
fn from(error: EntityDoesNotExistError) -> Self {
|
||||||
|
QueryEntityError::EntityDoesNotExist(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'w> core::error::Error for QueryEntityError<'w> {}
|
impl<'w> core::error::Error for QueryEntityError<'w> {}
|
||||||
|
|
||||||
impl<'w> core::fmt::Display for QueryEntityError<'w> {
|
impl<'w> core::fmt::Display for QueryEntityError<'w> {
|
||||||
@ -33,8 +39,8 @@ impl<'w> core::fmt::Display for QueryEntityError<'w> {
|
|||||||
)?;
|
)?;
|
||||||
format_archetype(f, world, entity)
|
format_archetype(f, world, entity)
|
||||||
}
|
}
|
||||||
Self::NoSuchEntity(entity, details) => {
|
Self::EntityDoesNotExist(error) => {
|
||||||
write!(f, "The entity with ID {entity} {details}")
|
write!(f, "{error}")
|
||||||
}
|
}
|
||||||
Self::AliasedMutability(entity) => {
|
Self::AliasedMutability(entity) => {
|
||||||
write!(
|
write!(
|
||||||
@ -54,8 +60,8 @@ impl<'w> core::fmt::Debug for QueryEntityError<'w> {
|
|||||||
format_archetype(f, world, entity)?;
|
format_archetype(f, world, entity)?;
|
||||||
write!(f, ")")
|
write!(f, ")")
|
||||||
}
|
}
|
||||||
Self::NoSuchEntity(entity, details) => {
|
Self::EntityDoesNotExist(error) => {
|
||||||
write!(f, "NoSuchEntity({entity} {details})")
|
write!(f, "EntityDoesNotExist({error})")
|
||||||
}
|
}
|
||||||
Self::AliasedMutability(entity) => write!(f, "AliasedMutability({entity})"),
|
Self::AliasedMutability(entity) => write!(f, "AliasedMutability({entity})"),
|
||||||
}
|
}
|
||||||
@ -88,7 +94,7 @@ impl<'w> PartialEq for QueryEntityError<'w> {
|
|||||||
fn eq(&self, other: &Self) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(Self::QueryDoesNotMatch(e1, _), Self::QueryDoesNotMatch(e2, _)) if e1 == e2 => true,
|
(Self::QueryDoesNotMatch(e1, _), Self::QueryDoesNotMatch(e2, _)) if e1 == e2 => true,
|
||||||
(Self::NoSuchEntity(e1, _), Self::NoSuchEntity(e2, _)) if e1 == e2 => true,
|
(Self::EntityDoesNotExist(e1), Self::EntityDoesNotExist(e2)) if e1 == e2 => true,
|
||||||
(Self::AliasedMutability(e1), Self::AliasedMutability(e2)) if e1 == e2 => true,
|
(Self::AliasedMutability(e1), Self::AliasedMutability(e2)) if e1 == e2 => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -949,7 +949,7 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
|
|||||||
///
|
///
|
||||||
/// let wrong_entity = Entity::from_raw(365);
|
/// let wrong_entity = Entity::from_raw(365);
|
||||||
///
|
///
|
||||||
/// assert_eq!(match query_state.get_many(&mut world, [wrong_entity]).unwrap_err() {QueryEntityError::NoSuchEntity(entity, _) => entity, _ => panic!()}, wrong_entity);
|
/// assert_eq!(match query_state.get_many(&mut world, [wrong_entity]).unwrap_err() {QueryEntityError::EntityDoesNotExist(error) => error.entity, _ => panic!()}, wrong_entity);
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_many<'w, const N: usize>(
|
pub fn get_many<'w, const N: usize>(
|
||||||
@ -1006,7 +1006,7 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
|
|||||||
/// let wrong_entity = Entity::from_raw(57);
|
/// let wrong_entity = Entity::from_raw(57);
|
||||||
/// let invalid_entity = world.spawn_empty().id();
|
/// let invalid_entity = world.spawn_empty().id();
|
||||||
///
|
///
|
||||||
/// assert_eq!(match query_state.get_many(&mut world, [wrong_entity]).unwrap_err() {QueryEntityError::NoSuchEntity(entity, _) => entity, _ => panic!()}, wrong_entity);
|
/// assert_eq!(match query_state.get_many(&mut world, [wrong_entity]).unwrap_err() {QueryEntityError::EntityDoesNotExist(error) => error.entity, _ => panic!()}, wrong_entity);
|
||||||
/// assert_eq!(match query_state.get_many_mut(&mut world, [invalid_entity]).unwrap_err() {QueryEntityError::QueryDoesNotMatch(entity, _) => entity, _ => panic!()}, invalid_entity);
|
/// assert_eq!(match query_state.get_many_mut(&mut world, [invalid_entity]).unwrap_err() {QueryEntityError::QueryDoesNotMatch(entity, _) => entity, _ => panic!()}, invalid_entity);
|
||||||
/// assert_eq!(query_state.get_many_mut(&mut world, [entities[0], entities[0]]).unwrap_err(), QueryEntityError::AliasedMutability(entities[0]));
|
/// assert_eq!(query_state.get_many_mut(&mut world, [entities[0], entities[0]]).unwrap_err(), QueryEntityError::AliasedMutability(entities[0]));
|
||||||
/// ```
|
/// ```
|
||||||
@ -1335,7 +1335,7 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
|
|||||||
/// # let wrong_entity = Entity::from_raw(57);
|
/// # let wrong_entity = Entity::from_raw(57);
|
||||||
/// # let invalid_entity = world.spawn_empty().id();
|
/// # let invalid_entity = world.spawn_empty().id();
|
||||||
///
|
///
|
||||||
/// # assert_eq!(match query_state.get_many(&mut world, [wrong_entity]).unwrap_err() {QueryEntityError::NoSuchEntity(entity, _) => entity, _ => panic!()}, wrong_entity);
|
/// # assert_eq!(match query_state.get_many(&mut world, [wrong_entity]).unwrap_err() {QueryEntityError::EntityDoesNotExist(error) => error.entity, _ => panic!()}, wrong_entity);
|
||||||
/// assert_eq!(match query_state.get_many_mut(&mut world, [invalid_entity]).unwrap_err() {QueryEntityError::QueryDoesNotMatch(entity, _) => entity, _ => panic!()}, invalid_entity);
|
/// assert_eq!(match query_state.get_many_mut(&mut world, [invalid_entity]).unwrap_err() {QueryEntityError::QueryDoesNotMatch(entity, _) => entity, _ => panic!()}, invalid_entity);
|
||||||
/// # assert_eq!(query_state.get_many_mut(&mut world, [entities[0], entities[0]]).unwrap_err(), QueryEntityError::AliasedMutability(entities[0]));
|
/// # assert_eq!(query_state.get_many_mut(&mut world, [entities[0], entities[0]]).unwrap_err(), QueryEntityError::AliasedMutability(entities[0]));
|
||||||
/// ```
|
/// ```
|
||||||
|
|||||||
@ -186,7 +186,7 @@ pub trait RelationshipTarget: Component<Mutability = Mutable> + Sized {
|
|||||||
let relationship_target = world.get_entity(entity).unwrap().get::<Self>().unwrap();
|
let relationship_target = world.get_entity(entity).unwrap().get::<Self>().unwrap();
|
||||||
let mut commands = world.get_raw_command_queue();
|
let mut commands = world.get_raw_command_queue();
|
||||||
for source_entity in relationship_target.iter() {
|
for source_entity in relationship_target.iter() {
|
||||||
if world.get_entity(source_entity).is_some() {
|
if world.get_entity(source_entity).is_ok() {
|
||||||
commands.push(
|
commands.push(
|
||||||
entity_command::remove::<Self::Relationship>()
|
entity_command::remove::<Self::Relationship>()
|
||||||
.with_entity(source_entity)
|
.with_entity(source_entity)
|
||||||
@ -217,7 +217,7 @@ pub trait RelationshipTarget: Component<Mutability = Mutable> + Sized {
|
|||||||
let relationship_target = world.get_entity(entity).unwrap().get::<Self>().unwrap();
|
let relationship_target = world.get_entity(entity).unwrap().get::<Self>().unwrap();
|
||||||
let mut commands = world.get_raw_command_queue();
|
let mut commands = world.get_raw_command_queue();
|
||||||
for source_entity in relationship_target.iter() {
|
for source_entity in relationship_target.iter() {
|
||||||
if world.get_entity(source_entity).is_some() {
|
if world.get_entity(source_entity).is_ok() {
|
||||||
commands.push(
|
commands.push(
|
||||||
entity_command::despawn()
|
entity_command::despawn()
|
||||||
.with_entity(source_entity)
|
.with_entity(source_entity)
|
||||||
|
|||||||
@ -15,7 +15,7 @@ use crate::{
|
|||||||
event::Event,
|
event::Event,
|
||||||
result::Result,
|
result::Result,
|
||||||
system::{command::HandleError, Command, IntoObserverSystem},
|
system::{command::HandleError, Command, IntoObserverSystem},
|
||||||
world::{error::EntityFetchError, EntityWorldMut, FromWorld, World},
|
world::{error::EntityMutableFetchError, EntityWorldMut, FromWorld, World},
|
||||||
};
|
};
|
||||||
use bevy_ptr::OwningPtr;
|
use bevy_ptr::OwningPtr;
|
||||||
|
|
||||||
@ -96,13 +96,13 @@ pub trait CommandWithEntity<Out> {
|
|||||||
fn with_entity(self, entity: Entity) -> impl Command<Out> + HandleError<Out>;
|
fn with_entity(self, entity: Entity) -> impl Command<Out> + HandleError<Out>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: EntityCommand> CommandWithEntity<Result<(), EntityFetchError>> for C {
|
impl<C: EntityCommand> CommandWithEntity<Result<(), EntityMutableFetchError>> for C {
|
||||||
fn with_entity(
|
fn with_entity(
|
||||||
self,
|
self,
|
||||||
entity: Entity,
|
entity: Entity,
|
||||||
) -> impl Command<Result<(), EntityFetchError>> + HandleError<Result<(), EntityFetchError>>
|
) -> impl Command<Result<(), EntityMutableFetchError>>
|
||||||
{
|
+ HandleError<Result<(), EntityMutableFetchError>> {
|
||||||
move |world: &mut World| -> Result<(), EntityFetchError> {
|
move |world: &mut World| -> Result<(), EntityMutableFetchError> {
|
||||||
let entity = world.get_entity_mut(entity)?;
|
let entity = world.get_entity_mut(entity)?;
|
||||||
self.apply(entity);
|
self.apply(entity);
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -134,7 +134,7 @@ impl<
|
|||||||
pub enum EntityCommandError<E> {
|
pub enum EntityCommandError<E> {
|
||||||
/// The entity this [`EntityCommand`] tried to run on could not be fetched.
|
/// The entity this [`EntityCommand`] tried to run on could not be fetched.
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
EntityFetchError(#[from] EntityFetchError),
|
EntityFetchError(#[from] EntityMutableFetchError),
|
||||||
/// An error that occurred while running the [`EntityCommand`].
|
/// An error that occurred while running the [`EntityCommand`].
|
||||||
#[error("{0}")]
|
#[error("{0}")]
|
||||||
CommandFailed(E),
|
CommandFailed(E),
|
||||||
@ -300,6 +300,7 @@ pub fn log_components() -> impl EntityCommand {
|
|||||||
let debug_infos: Vec<_> = entity
|
let debug_infos: Vec<_> = entity
|
||||||
.world()
|
.world()
|
||||||
.inspect_entity(entity.id())
|
.inspect_entity(entity.id())
|
||||||
|
.expect("Entity existence is verified before an EntityCommand is executed")
|
||||||
.map(ComponentInfo::name)
|
.map(ComponentInfo::name)
|
||||||
.collect();
|
.collect();
|
||||||
info!("Entity {}: {debug_infos:?}", entity.id());
|
info!("Entity {}: {debug_infos:?}", entity.id());
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
batching::BatchingStrategy,
|
batching::BatchingStrategy,
|
||||||
component::Tick,
|
component::Tick,
|
||||||
entity::{Entity, EntityBorrow, EntitySet},
|
entity::{Entity, EntityBorrow, EntityDoesNotExistError, EntitySet},
|
||||||
query::{
|
query::{
|
||||||
DebugCheckedUnwrap, NopWorldQuery, QueryCombinationIter, QueryData, QueryEntityError,
|
DebugCheckedUnwrap, NopWorldQuery, QueryCombinationIter, QueryData, QueryEntityError,
|
||||||
QueryFilter, QueryIter, QueryManyIter, QueryManyUniqueIter, QueryParIter, QueryParManyIter,
|
QueryFilter, QueryIter, QueryManyIter, QueryManyUniqueIter, QueryParIter, QueryParManyIter,
|
||||||
@ -1310,7 +1310,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
|
|||||||
///
|
///
|
||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
/// match query.get_many([wrong_entity]).unwrap_err() {
|
/// match query.get_many([wrong_entity]).unwrap_err() {
|
||||||
/// QueryEntityError::NoSuchEntity(entity, _) => entity,
|
/// QueryEntityError::EntityDoesNotExist(error) => error.entity,
|
||||||
/// _ => panic!(),
|
/// _ => panic!(),
|
||||||
/// },
|
/// },
|
||||||
/// wrong_entity
|
/// wrong_entity
|
||||||
@ -1430,16 +1430,11 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
|
|||||||
// SAFETY: system runs without conflicts with other systems.
|
// SAFETY: system runs without conflicts with other systems.
|
||||||
// same-system queries have runtime borrow checks when they conflict
|
// same-system queries have runtime borrow checks when they conflict
|
||||||
unsafe {
|
unsafe {
|
||||||
let location =
|
let location = self
|
||||||
self.world
|
.world
|
||||||
.entities()
|
.entities()
|
||||||
.get(entity)
|
.get(entity)
|
||||||
.ok_or(QueryEntityError::NoSuchEntity(
|
.ok_or(EntityDoesNotExistError::new(entity, self.world.entities()))?;
|
||||||
entity,
|
|
||||||
self.world
|
|
||||||
.entities()
|
|
||||||
.entity_does_not_exist_error_details(entity),
|
|
||||||
))?;
|
|
||||||
if !self
|
if !self
|
||||||
.state
|
.state
|
||||||
.matched_archetypes
|
.matched_archetypes
|
||||||
@ -1524,7 +1519,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
|
|||||||
/// .get_many_mut([wrong_entity])
|
/// .get_many_mut([wrong_entity])
|
||||||
/// .unwrap_err()
|
/// .unwrap_err()
|
||||||
/// {
|
/// {
|
||||||
/// QueryEntityError::NoSuchEntity(entity, _) => entity,
|
/// QueryEntityError::EntityDoesNotExist(error) => error.entity,
|
||||||
/// _ => panic!(),
|
/// _ => panic!(),
|
||||||
/// },
|
/// },
|
||||||
/// wrong_entity
|
/// wrong_entity
|
||||||
|
|||||||
@ -12,7 +12,7 @@ use crate::{
|
|||||||
resource::Resource,
|
resource::Resource,
|
||||||
system::{Commands, Query},
|
system::{Commands, Query},
|
||||||
traversal::Traversal,
|
traversal::Traversal,
|
||||||
world::{error::EntityFetchError, WorldEntityFetch},
|
world::{error::EntityMutableFetchError, WorldEntityFetch},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{unsafe_world_cell::UnsafeWorldCell, Mut, World, ON_INSERT, ON_REPLACE};
|
use super::{unsafe_world_cell::UnsafeWorldCell, Mut, World, ON_INSERT, ON_REPLACE};
|
||||||
@ -94,24 +94,13 @@ impl<'w> DeferredWorld<'w> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
entity: Entity,
|
entity: Entity,
|
||||||
f: impl FnOnce(&mut T) -> R,
|
f: impl FnOnce(&mut T) -> R,
|
||||||
) -> Result<Option<R>, EntityFetchError> {
|
) -> Result<Option<R>, EntityMutableFetchError> {
|
||||||
// If the component is not registered, then it doesn't exist on this entity, so no action required.
|
// If the component is not registered, then it doesn't exist on this entity, so no action required.
|
||||||
let Some(component_id) = self.component_id::<T>() else {
|
let Some(component_id) = self.component_id::<T>() else {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
};
|
};
|
||||||
|
|
||||||
let entity_cell = match self.get_entity_mut(entity) {
|
let entity_cell = self.get_entity_mut(entity)?;
|
||||||
Ok(cell) => cell,
|
|
||||||
Err(EntityFetchError::AliasedMutability(..)) => {
|
|
||||||
return Err(EntityFetchError::AliasedMutability(entity))
|
|
||||||
}
|
|
||||||
Err(EntityFetchError::NoSuchEntity(..)) => {
|
|
||||||
return Err(EntityFetchError::NoSuchEntity(
|
|
||||||
entity,
|
|
||||||
self.entities().entity_does_not_exist_error_details(entity),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if !entity_cell.contains::<T>() {
|
if !entity_cell.contains::<T>() {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
@ -201,9 +190,9 @@ impl<'w> DeferredWorld<'w> {
|
|||||||
///
|
///
|
||||||
/// # Errors
|
/// # Errors
|
||||||
///
|
///
|
||||||
/// - Returns [`EntityFetchError::NoSuchEntity`] if any of the given `entities` do not exist in the world.
|
/// - Returns [`EntityMutableFetchError::EntityDoesNotExist`] if any of the given `entities` do not exist in the world.
|
||||||
/// - Only the first entity found to be missing will be returned.
|
/// - Only the first entity found to be missing will be returned.
|
||||||
/// - Returns [`EntityFetchError::AliasedMutability`] if the same entity is requested multiple times.
|
/// - Returns [`EntityMutableFetchError::AliasedMutability`] if the same entity is requested multiple times.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
@ -217,7 +206,7 @@ impl<'w> DeferredWorld<'w> {
|
|||||||
pub fn get_entity_mut<F: WorldEntityFetch>(
|
pub fn get_entity_mut<F: WorldEntityFetch>(
|
||||||
&mut self,
|
&mut self,
|
||||||
entities: F,
|
entities: F,
|
||||||
) -> Result<F::DeferredMut<'_>, EntityFetchError> {
|
) -> Result<F::DeferredMut<'_>, EntityMutableFetchError> {
|
||||||
let cell = self.as_unsafe_world_cell();
|
let cell = self.as_unsafe_world_cell();
|
||||||
// SAFETY: `&mut self` gives mutable access to the entire world,
|
// SAFETY: `&mut self` gives mutable access to the entire world,
|
||||||
// and prevents any other access to the world.
|
// and prevents any other access to the world.
|
||||||
|
|||||||
@ -2,9 +2,9 @@ use alloc::vec::Vec;
|
|||||||
use core::mem::MaybeUninit;
|
use core::mem::MaybeUninit;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
entity::{hash_map::EntityHashMap, hash_set::EntityHashSet, Entity},
|
entity::{hash_map::EntityHashMap, hash_set::EntityHashSet, Entity, EntityDoesNotExistError},
|
||||||
world::{
|
world::{
|
||||||
error::EntityFetchError, unsafe_world_cell::UnsafeWorldCell, EntityMut, EntityRef,
|
error::EntityMutableFetchError, unsafe_world_cell::UnsafeWorldCell, EntityMut, EntityRef,
|
||||||
EntityWorldMut,
|
EntityWorldMut,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -56,8 +56,11 @@ pub unsafe trait WorldEntityFetch {
|
|||||||
///
|
///
|
||||||
/// # Errors
|
/// # Errors
|
||||||
///
|
///
|
||||||
/// - Returns [`Entity`] if the entity does not exist.
|
/// - Returns [`EntityDoesNotExistError`] if the entity does not exist.
|
||||||
unsafe fn fetch_ref(self, cell: UnsafeWorldCell<'_>) -> Result<Self::Ref<'_>, Entity>;
|
unsafe fn fetch_ref(
|
||||||
|
self,
|
||||||
|
cell: UnsafeWorldCell<'_>,
|
||||||
|
) -> Result<Self::Ref<'_>, EntityDoesNotExistError>;
|
||||||
|
|
||||||
/// Returns mutable reference(s) to the entities with the given [`Entity`]
|
/// Returns mutable reference(s) to the entities with the given [`Entity`]
|
||||||
/// IDs, as determined by `self`.
|
/// IDs, as determined by `self`.
|
||||||
@ -70,11 +73,13 @@ pub unsafe trait WorldEntityFetch {
|
|||||||
///
|
///
|
||||||
/// # Errors
|
/// # Errors
|
||||||
///
|
///
|
||||||
/// - Returns [`EntityFetchError::NoSuchEntity`] if the entity does not exist.
|
/// - Returns [`EntityMutableFetchError::EntityDoesNotExist`] if the entity does not exist.
|
||||||
/// - Returns [`EntityFetchError::AliasedMutability`] if the entity was
|
/// - Returns [`EntityMutableFetchError::AliasedMutability`] if the entity was
|
||||||
/// requested mutably more than once.
|
/// requested mutably more than once.
|
||||||
unsafe fn fetch_mut(self, cell: UnsafeWorldCell<'_>)
|
unsafe fn fetch_mut(
|
||||||
-> Result<Self::Mut<'_>, EntityFetchError>;
|
self,
|
||||||
|
cell: UnsafeWorldCell<'_>,
|
||||||
|
) -> Result<Self::Mut<'_>, EntityMutableFetchError>;
|
||||||
|
|
||||||
/// Returns mutable reference(s) to the entities with the given [`Entity`]
|
/// Returns mutable reference(s) to the entities with the given [`Entity`]
|
||||||
/// IDs, as determined by `self`, but without structural mutability.
|
/// IDs, as determined by `self`, but without structural mutability.
|
||||||
@ -91,13 +96,13 @@ pub unsafe trait WorldEntityFetch {
|
|||||||
///
|
///
|
||||||
/// # Errors
|
/// # Errors
|
||||||
///
|
///
|
||||||
/// - Returns [`EntityFetchError::NoSuchEntity`] if the entity does not exist.
|
/// - Returns [`EntityMutableFetchError::EntityDoesNotExist`] if the entity does not exist.
|
||||||
/// - Returns [`EntityFetchError::AliasedMutability`] if the entity was
|
/// - Returns [`EntityMutableFetchError::AliasedMutability`] if the entity was
|
||||||
/// requested mutably more than once.
|
/// requested mutably more than once.
|
||||||
unsafe fn fetch_deferred_mut(
|
unsafe fn fetch_deferred_mut(
|
||||||
self,
|
self,
|
||||||
cell: UnsafeWorldCell<'_>,
|
cell: UnsafeWorldCell<'_>,
|
||||||
) -> Result<Self::DeferredMut<'_>, EntityFetchError>;
|
) -> Result<Self::DeferredMut<'_>, EntityMutableFetchError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
// SAFETY:
|
// SAFETY:
|
||||||
@ -109,8 +114,11 @@ unsafe impl WorldEntityFetch for Entity {
|
|||||||
type Mut<'w> = EntityWorldMut<'w>;
|
type Mut<'w> = EntityWorldMut<'w>;
|
||||||
type DeferredMut<'w> = EntityMut<'w>;
|
type DeferredMut<'w> = EntityMut<'w>;
|
||||||
|
|
||||||
unsafe fn fetch_ref(self, cell: UnsafeWorldCell<'_>) -> Result<Self::Ref<'_>, Entity> {
|
unsafe fn fetch_ref(
|
||||||
let ecell = cell.get_entity(self).ok_or(self)?;
|
self,
|
||||||
|
cell: UnsafeWorldCell<'_>,
|
||||||
|
) -> Result<Self::Ref<'_>, EntityDoesNotExistError> {
|
||||||
|
let ecell = cell.get_entity(self)?;
|
||||||
// SAFETY: caller ensures that the world cell has read-only access to the entity.
|
// SAFETY: caller ensures that the world cell has read-only access to the entity.
|
||||||
Ok(unsafe { EntityRef::new(ecell) })
|
Ok(unsafe { EntityRef::new(ecell) })
|
||||||
}
|
}
|
||||||
@ -118,14 +126,11 @@ unsafe impl WorldEntityFetch for Entity {
|
|||||||
unsafe fn fetch_mut(
|
unsafe fn fetch_mut(
|
||||||
self,
|
self,
|
||||||
cell: UnsafeWorldCell<'_>,
|
cell: UnsafeWorldCell<'_>,
|
||||||
) -> Result<Self::Mut<'_>, EntityFetchError> {
|
) -> Result<Self::Mut<'_>, EntityMutableFetchError> {
|
||||||
let location = cell
|
let location = cell
|
||||||
.entities()
|
.entities()
|
||||||
.get(self)
|
.get(self)
|
||||||
.ok_or(EntityFetchError::NoSuchEntity(
|
.ok_or(EntityDoesNotExistError::new(self, cell.entities()))?;
|
||||||
self,
|
|
||||||
cell.entities().entity_does_not_exist_error_details(self),
|
|
||||||
))?;
|
|
||||||
// SAFETY: caller ensures that the world cell has mutable access to the entity.
|
// SAFETY: caller ensures that the world cell has mutable access to the entity.
|
||||||
let world = unsafe { cell.world_mut() };
|
let world = unsafe { cell.world_mut() };
|
||||||
// SAFETY: location was fetched from the same world's `Entities`.
|
// SAFETY: location was fetched from the same world's `Entities`.
|
||||||
@ -135,11 +140,8 @@ unsafe impl WorldEntityFetch for Entity {
|
|||||||
unsafe fn fetch_deferred_mut(
|
unsafe fn fetch_deferred_mut(
|
||||||
self,
|
self,
|
||||||
cell: UnsafeWorldCell<'_>,
|
cell: UnsafeWorldCell<'_>,
|
||||||
) -> Result<Self::DeferredMut<'_>, EntityFetchError> {
|
) -> Result<Self::DeferredMut<'_>, EntityMutableFetchError> {
|
||||||
let ecell = cell.get_entity(self).ok_or(EntityFetchError::NoSuchEntity(
|
let ecell = cell.get_entity(self)?;
|
||||||
self,
|
|
||||||
cell.entities().entity_does_not_exist_error_details(self),
|
|
||||||
))?;
|
|
||||||
// SAFETY: caller ensures that the world cell has mutable access to the entity.
|
// SAFETY: caller ensures that the world cell has mutable access to the entity.
|
||||||
Ok(unsafe { EntityMut::new(ecell) })
|
Ok(unsafe { EntityMut::new(ecell) })
|
||||||
}
|
}
|
||||||
@ -154,21 +156,24 @@ unsafe impl<const N: usize> WorldEntityFetch for [Entity; N] {
|
|||||||
type Mut<'w> = [EntityMut<'w>; N];
|
type Mut<'w> = [EntityMut<'w>; N];
|
||||||
type DeferredMut<'w> = [EntityMut<'w>; N];
|
type DeferredMut<'w> = [EntityMut<'w>; N];
|
||||||
|
|
||||||
unsafe fn fetch_ref(self, cell: UnsafeWorldCell<'_>) -> Result<Self::Ref<'_>, Entity> {
|
unsafe fn fetch_ref(
|
||||||
|
self,
|
||||||
|
cell: UnsafeWorldCell<'_>,
|
||||||
|
) -> Result<Self::Ref<'_>, EntityDoesNotExistError> {
|
||||||
<&Self>::fetch_ref(&self, cell)
|
<&Self>::fetch_ref(&self, cell)
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn fetch_mut(
|
unsafe fn fetch_mut(
|
||||||
self,
|
self,
|
||||||
cell: UnsafeWorldCell<'_>,
|
cell: UnsafeWorldCell<'_>,
|
||||||
) -> Result<Self::Mut<'_>, EntityFetchError> {
|
) -> Result<Self::Mut<'_>, EntityMutableFetchError> {
|
||||||
<&Self>::fetch_mut(&self, cell)
|
<&Self>::fetch_mut(&self, cell)
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn fetch_deferred_mut(
|
unsafe fn fetch_deferred_mut(
|
||||||
self,
|
self,
|
||||||
cell: UnsafeWorldCell<'_>,
|
cell: UnsafeWorldCell<'_>,
|
||||||
) -> Result<Self::DeferredMut<'_>, EntityFetchError> {
|
) -> Result<Self::DeferredMut<'_>, EntityMutableFetchError> {
|
||||||
<&Self>::fetch_deferred_mut(&self, cell)
|
<&Self>::fetch_deferred_mut(&self, cell)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -182,10 +187,13 @@ unsafe impl<const N: usize> WorldEntityFetch for &'_ [Entity; N] {
|
|||||||
type Mut<'w> = [EntityMut<'w>; N];
|
type Mut<'w> = [EntityMut<'w>; N];
|
||||||
type DeferredMut<'w> = [EntityMut<'w>; N];
|
type DeferredMut<'w> = [EntityMut<'w>; N];
|
||||||
|
|
||||||
unsafe fn fetch_ref(self, cell: UnsafeWorldCell<'_>) -> Result<Self::Ref<'_>, Entity> {
|
unsafe fn fetch_ref(
|
||||||
|
self,
|
||||||
|
cell: UnsafeWorldCell<'_>,
|
||||||
|
) -> Result<Self::Ref<'_>, EntityDoesNotExistError> {
|
||||||
let mut refs = [MaybeUninit::uninit(); N];
|
let mut refs = [MaybeUninit::uninit(); N];
|
||||||
for (r, &id) in core::iter::zip(&mut refs, self) {
|
for (r, &id) in core::iter::zip(&mut refs, self) {
|
||||||
let ecell = cell.get_entity(id).ok_or(id)?;
|
let ecell = cell.get_entity(id)?;
|
||||||
// SAFETY: caller ensures that the world cell has read-only access to the entity.
|
// SAFETY: caller ensures that the world cell has read-only access to the entity.
|
||||||
*r = MaybeUninit::new(unsafe { EntityRef::new(ecell) });
|
*r = MaybeUninit::new(unsafe { EntityRef::new(ecell) });
|
||||||
}
|
}
|
||||||
@ -199,22 +207,19 @@ unsafe impl<const N: usize> WorldEntityFetch for &'_ [Entity; N] {
|
|||||||
unsafe fn fetch_mut(
|
unsafe fn fetch_mut(
|
||||||
self,
|
self,
|
||||||
cell: UnsafeWorldCell<'_>,
|
cell: UnsafeWorldCell<'_>,
|
||||||
) -> Result<Self::Mut<'_>, EntityFetchError> {
|
) -> Result<Self::Mut<'_>, EntityMutableFetchError> {
|
||||||
// Check for duplicate entities.
|
// Check for duplicate entities.
|
||||||
for i in 0..self.len() {
|
for i in 0..self.len() {
|
||||||
for j in 0..i {
|
for j in 0..i {
|
||||||
if self[i] == self[j] {
|
if self[i] == self[j] {
|
||||||
return Err(EntityFetchError::AliasedMutability(self[i]));
|
return Err(EntityMutableFetchError::AliasedMutability(self[i]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut refs = [const { MaybeUninit::uninit() }; N];
|
let mut refs = [const { MaybeUninit::uninit() }; N];
|
||||||
for (r, &id) in core::iter::zip(&mut refs, self) {
|
for (r, &id) in core::iter::zip(&mut refs, self) {
|
||||||
let ecell = cell.get_entity(id).ok_or(EntityFetchError::NoSuchEntity(
|
let ecell = cell.get_entity(id)?;
|
||||||
id,
|
|
||||||
cell.entities().entity_does_not_exist_error_details(id),
|
|
||||||
))?;
|
|
||||||
// SAFETY: caller ensures that the world cell has mutable access to the entity.
|
// SAFETY: caller ensures that the world cell has mutable access to the entity.
|
||||||
*r = MaybeUninit::new(unsafe { EntityMut::new(ecell) });
|
*r = MaybeUninit::new(unsafe { EntityMut::new(ecell) });
|
||||||
}
|
}
|
||||||
@ -228,7 +233,7 @@ unsafe impl<const N: usize> WorldEntityFetch for &'_ [Entity; N] {
|
|||||||
unsafe fn fetch_deferred_mut(
|
unsafe fn fetch_deferred_mut(
|
||||||
self,
|
self,
|
||||||
cell: UnsafeWorldCell<'_>,
|
cell: UnsafeWorldCell<'_>,
|
||||||
) -> Result<Self::DeferredMut<'_>, EntityFetchError> {
|
) -> Result<Self::DeferredMut<'_>, EntityMutableFetchError> {
|
||||||
// SAFETY: caller ensures that the world cell has mutable access to the entity,
|
// SAFETY: caller ensures that the world cell has mutable access to the entity,
|
||||||
// and `fetch_mut` does not return structurally-mutable references.
|
// and `fetch_mut` does not return structurally-mutable references.
|
||||||
unsafe { self.fetch_mut(cell) }
|
unsafe { self.fetch_mut(cell) }
|
||||||
@ -244,10 +249,13 @@ unsafe impl WorldEntityFetch for &'_ [Entity] {
|
|||||||
type Mut<'w> = Vec<EntityMut<'w>>;
|
type Mut<'w> = Vec<EntityMut<'w>>;
|
||||||
type DeferredMut<'w> = Vec<EntityMut<'w>>;
|
type DeferredMut<'w> = Vec<EntityMut<'w>>;
|
||||||
|
|
||||||
unsafe fn fetch_ref(self, cell: UnsafeWorldCell<'_>) -> Result<Self::Ref<'_>, Entity> {
|
unsafe fn fetch_ref(
|
||||||
|
self,
|
||||||
|
cell: UnsafeWorldCell<'_>,
|
||||||
|
) -> Result<Self::Ref<'_>, EntityDoesNotExistError> {
|
||||||
let mut refs = Vec::with_capacity(self.len());
|
let mut refs = Vec::with_capacity(self.len());
|
||||||
for &id in self {
|
for &id in self {
|
||||||
let ecell = cell.get_entity(id).ok_or(id)?;
|
let ecell = cell.get_entity(id)?;
|
||||||
// SAFETY: caller ensures that the world cell has read-only access to the entity.
|
// SAFETY: caller ensures that the world cell has read-only access to the entity.
|
||||||
refs.push(unsafe { EntityRef::new(ecell) });
|
refs.push(unsafe { EntityRef::new(ecell) });
|
||||||
}
|
}
|
||||||
@ -258,22 +266,19 @@ unsafe impl WorldEntityFetch for &'_ [Entity] {
|
|||||||
unsafe fn fetch_mut(
|
unsafe fn fetch_mut(
|
||||||
self,
|
self,
|
||||||
cell: UnsafeWorldCell<'_>,
|
cell: UnsafeWorldCell<'_>,
|
||||||
) -> Result<Self::Mut<'_>, EntityFetchError> {
|
) -> Result<Self::Mut<'_>, EntityMutableFetchError> {
|
||||||
// Check for duplicate entities.
|
// Check for duplicate entities.
|
||||||
for i in 0..self.len() {
|
for i in 0..self.len() {
|
||||||
for j in 0..i {
|
for j in 0..i {
|
||||||
if self[i] == self[j] {
|
if self[i] == self[j] {
|
||||||
return Err(EntityFetchError::AliasedMutability(self[i]));
|
return Err(EntityMutableFetchError::AliasedMutability(self[i]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut refs = Vec::with_capacity(self.len());
|
let mut refs = Vec::with_capacity(self.len());
|
||||||
for &id in self {
|
for &id in self {
|
||||||
let ecell = cell.get_entity(id).ok_or(EntityFetchError::NoSuchEntity(
|
let ecell = cell.get_entity(id)?;
|
||||||
id,
|
|
||||||
cell.entities().entity_does_not_exist_error_details(id),
|
|
||||||
))?;
|
|
||||||
// SAFETY: caller ensures that the world cell has mutable access to the entity.
|
// SAFETY: caller ensures that the world cell has mutable access to the entity.
|
||||||
refs.push(unsafe { EntityMut::new(ecell) });
|
refs.push(unsafe { EntityMut::new(ecell) });
|
||||||
}
|
}
|
||||||
@ -284,7 +289,7 @@ unsafe impl WorldEntityFetch for &'_ [Entity] {
|
|||||||
unsafe fn fetch_deferred_mut(
|
unsafe fn fetch_deferred_mut(
|
||||||
self,
|
self,
|
||||||
cell: UnsafeWorldCell<'_>,
|
cell: UnsafeWorldCell<'_>,
|
||||||
) -> Result<Self::DeferredMut<'_>, EntityFetchError> {
|
) -> Result<Self::DeferredMut<'_>, EntityMutableFetchError> {
|
||||||
// SAFETY: caller ensures that the world cell has mutable access to the entity,
|
// SAFETY: caller ensures that the world cell has mutable access to the entity,
|
||||||
// and `fetch_mut` does not return structurally-mutable references.
|
// and `fetch_mut` does not return structurally-mutable references.
|
||||||
unsafe { self.fetch_mut(cell) }
|
unsafe { self.fetch_mut(cell) }
|
||||||
@ -300,10 +305,13 @@ unsafe impl WorldEntityFetch for &'_ EntityHashSet {
|
|||||||
type Mut<'w> = EntityHashMap<EntityMut<'w>>;
|
type Mut<'w> = EntityHashMap<EntityMut<'w>>;
|
||||||
type DeferredMut<'w> = EntityHashMap<EntityMut<'w>>;
|
type DeferredMut<'w> = EntityHashMap<EntityMut<'w>>;
|
||||||
|
|
||||||
unsafe fn fetch_ref(self, cell: UnsafeWorldCell<'_>) -> Result<Self::Ref<'_>, Entity> {
|
unsafe fn fetch_ref(
|
||||||
|
self,
|
||||||
|
cell: UnsafeWorldCell<'_>,
|
||||||
|
) -> Result<Self::Ref<'_>, EntityDoesNotExistError> {
|
||||||
let mut refs = EntityHashMap::with_capacity(self.len());
|
let mut refs = EntityHashMap::with_capacity(self.len());
|
||||||
for &id in self {
|
for &id in self {
|
||||||
let ecell = cell.get_entity(id).ok_or(id)?;
|
let ecell = cell.get_entity(id)?;
|
||||||
// SAFETY: caller ensures that the world cell has read-only access to the entity.
|
// SAFETY: caller ensures that the world cell has read-only access to the entity.
|
||||||
refs.insert(id, unsafe { EntityRef::new(ecell) });
|
refs.insert(id, unsafe { EntityRef::new(ecell) });
|
||||||
}
|
}
|
||||||
@ -313,13 +321,10 @@ unsafe impl WorldEntityFetch for &'_ EntityHashSet {
|
|||||||
unsafe fn fetch_mut(
|
unsafe fn fetch_mut(
|
||||||
self,
|
self,
|
||||||
cell: UnsafeWorldCell<'_>,
|
cell: UnsafeWorldCell<'_>,
|
||||||
) -> Result<Self::Mut<'_>, EntityFetchError> {
|
) -> Result<Self::Mut<'_>, EntityMutableFetchError> {
|
||||||
let mut refs = EntityHashMap::with_capacity(self.len());
|
let mut refs = EntityHashMap::with_capacity(self.len());
|
||||||
for &id in self {
|
for &id in self {
|
||||||
let ecell = cell.get_entity(id).ok_or(EntityFetchError::NoSuchEntity(
|
let ecell = cell.get_entity(id)?;
|
||||||
id,
|
|
||||||
cell.entities().entity_does_not_exist_error_details(id),
|
|
||||||
))?;
|
|
||||||
// SAFETY: caller ensures that the world cell has mutable access to the entity.
|
// SAFETY: caller ensures that the world cell has mutable access to the entity.
|
||||||
refs.insert(id, unsafe { EntityMut::new(ecell) });
|
refs.insert(id, unsafe { EntityMut::new(ecell) });
|
||||||
}
|
}
|
||||||
@ -329,7 +334,7 @@ unsafe impl WorldEntityFetch for &'_ EntityHashSet {
|
|||||||
unsafe fn fetch_deferred_mut(
|
unsafe fn fetch_deferred_mut(
|
||||||
self,
|
self,
|
||||||
cell: UnsafeWorldCell<'_>,
|
cell: UnsafeWorldCell<'_>,
|
||||||
) -> Result<Self::DeferredMut<'_>, EntityFetchError> {
|
) -> Result<Self::DeferredMut<'_>, EntityMutableFetchError> {
|
||||||
// SAFETY: caller ensures that the world cell has mutable access to the entity,
|
// SAFETY: caller ensures that the world cell has mutable access to the entity,
|
||||||
// and `fetch_mut` does not return structurally-mutable references.
|
// and `fetch_mut` does not return structurally-mutable references.
|
||||||
unsafe { self.fetch_mut(cell) }
|
unsafe { self.fetch_mut(cell) }
|
||||||
|
|||||||
@ -1,39 +1,26 @@
|
|||||||
//! Contains error types returned by bevy's schedule.
|
//! Contains error types returned by bevy's schedule.
|
||||||
|
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use thiserror::Error;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
component::ComponentId,
|
component::ComponentId,
|
||||||
entity::{Entity, EntityDoesNotExistDetails},
|
entity::{Entity, EntityDoesNotExistError},
|
||||||
schedule::InternedScheduleLabel,
|
schedule::InternedScheduleLabel,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The error type returned by [`World::try_run_schedule`] if the provided schedule does not exist.
|
/// The error type returned by [`World::try_run_schedule`] if the provided schedule does not exist.
|
||||||
///
|
///
|
||||||
/// [`World::try_run_schedule`]: crate::world::World::try_run_schedule
|
/// [`World::try_run_schedule`]: crate::world::World::try_run_schedule
|
||||||
#[derive(Error, Debug)]
|
#[derive(thiserror::Error, Debug)]
|
||||||
#[error("The schedule with the label {0:?} was not found.")]
|
#[error("The schedule with the label {0:?} was not found.")]
|
||||||
pub struct TryRunScheduleError(pub InternedScheduleLabel);
|
pub struct TryRunScheduleError(pub InternedScheduleLabel);
|
||||||
|
|
||||||
/// The error type returned by [`World::try_despawn`] if the provided entity does not exist.
|
|
||||||
///
|
|
||||||
/// [`World::try_despawn`]: crate::world::World::try_despawn
|
|
||||||
#[derive(Error, Debug, Clone, Copy)]
|
|
||||||
#[error("Could not despawn the entity with ID {entity} because it {details}")]
|
|
||||||
pub struct TryDespawnError {
|
|
||||||
/// The entity's ID.
|
|
||||||
pub entity: Entity,
|
|
||||||
/// Details on why the entity does not exist, if available.
|
|
||||||
pub details: EntityDoesNotExistDetails,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The error type returned by [`World::try_insert_batch`] and [`World::try_insert_batch_if_new`]
|
/// The error type returned by [`World::try_insert_batch`] and [`World::try_insert_batch_if_new`]
|
||||||
/// if any of the provided entities do not exist.
|
/// if any of the provided entities do not exist.
|
||||||
///
|
///
|
||||||
/// [`World::try_insert_batch`]: crate::world::World::try_insert_batch
|
/// [`World::try_insert_batch`]: crate::world::World::try_insert_batch
|
||||||
/// [`World::try_insert_batch_if_new`]: crate::world::World::try_insert_batch_if_new
|
/// [`World::try_insert_batch_if_new`]: crate::world::World::try_insert_batch_if_new
|
||||||
#[derive(Error, Debug, Clone)]
|
#[derive(thiserror::Error, Debug, Clone)]
|
||||||
#[error("Could not insert bundles of type {bundle_type} into the entities with the following IDs because they do not exist: {entities:?}")]
|
#[error("Could not insert bundles of type {bundle_type} into the entities with the following IDs because they do not exist: {entities:?}")]
|
||||||
pub struct TryInsertBatchError {
|
pub struct TryInsertBatchError {
|
||||||
/// The bundles' type name.
|
/// The bundles' type name.
|
||||||
@ -42,8 +29,13 @@ pub struct TryInsertBatchError {
|
|||||||
pub entities: Vec<Entity>,
|
pub entities: Vec<Entity>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An error that occurs when a specified [`Entity`] could not be despawned.
|
||||||
|
#[derive(thiserror::Error, Debug, Clone, Copy)]
|
||||||
|
#[error("Could not despawn entity: {0}")]
|
||||||
|
pub struct EntityDespawnError(#[from] pub EntityMutableFetchError);
|
||||||
|
|
||||||
/// An error that occurs when dynamically retrieving components from an entity.
|
/// An error that occurs when dynamically retrieving components from an entity.
|
||||||
#[derive(Error, Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(thiserror::Error, Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum EntityComponentError {
|
pub enum EntityComponentError {
|
||||||
/// The component with the given [`ComponentId`] does not exist on the entity.
|
/// The component with the given [`ComponentId`] does not exist on the entity.
|
||||||
#[error("The component with ID {0:?} does not exist on the entity.")]
|
#[error("The component with ID {0:?} does not exist on the entity.")]
|
||||||
@ -54,24 +46,12 @@ pub enum EntityComponentError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// An error that occurs when fetching entities mutably from a world.
|
/// An error that occurs when fetching entities mutably from a world.
|
||||||
#[derive(Error, Debug, Clone, Copy)]
|
#[derive(thiserror::Error, Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum EntityFetchError {
|
pub enum EntityMutableFetchError {
|
||||||
/// The entity with the given ID does not exist.
|
/// The entity with the given ID does not exist.
|
||||||
#[error("The entity with ID {0} {1}")]
|
#[error(transparent)]
|
||||||
NoSuchEntity(Entity, EntityDoesNotExistDetails),
|
EntityDoesNotExist(#[from] EntityDoesNotExistError),
|
||||||
/// The entity with the given ID was requested mutably more than once.
|
/// The entity with the given ID was requested mutably more than once.
|
||||||
#[error("The entity with ID {0} was requested mutably more than once")]
|
#[error("The entity with ID {0} was requested mutably more than once")]
|
||||||
AliasedMutability(Entity),
|
AliasedMutability(Entity),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for EntityFetchError {
|
|
||||||
fn eq(&self, other: &Self) -> bool {
|
|
||||||
match (self, other) {
|
|
||||||
(Self::NoSuchEntity(e1, _), Self::NoSuchEntity(e2, _)) if e1 == e2 => true,
|
|
||||||
(Self::AliasedMutability(e1), Self::AliasedMutability(e2)) if e1 == e2 => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Eq for EntityFetchError {}
|
|
||||||
|
|||||||
@ -41,7 +41,9 @@ use crate::{
|
|||||||
Component, ComponentDescriptor, ComponentHooks, ComponentId, ComponentInfo, ComponentTicks,
|
Component, ComponentDescriptor, ComponentHooks, ComponentId, ComponentInfo, ComponentTicks,
|
||||||
Components, Mutable, RequiredComponents, RequiredComponentsError, Tick,
|
Components, Mutable, RequiredComponents, RequiredComponentsError, Tick,
|
||||||
},
|
},
|
||||||
entity::{AllocAtWithoutReplacement, Entities, Entity, EntityLocation},
|
entity::{
|
||||||
|
AllocAtWithoutReplacement, Entities, Entity, EntityDoesNotExistError, EntityLocation,
|
||||||
|
},
|
||||||
entity_disabling::DefaultQueryFilters,
|
entity_disabling::DefaultQueryFilters,
|
||||||
event::{Event, EventId, Events, SendBatchIds},
|
event::{Event, EventId, Events, SendBatchIds},
|
||||||
observer::Observers,
|
observer::Observers,
|
||||||
@ -53,7 +55,9 @@ use crate::{
|
|||||||
system::Commands,
|
system::Commands,
|
||||||
world::{
|
world::{
|
||||||
command_queue::RawCommandQueue,
|
command_queue::RawCommandQueue,
|
||||||
error::{EntityFetchError, TryDespawnError, TryInsertBatchError, TryRunScheduleError},
|
error::{
|
||||||
|
EntityDespawnError, EntityMutableFetchError, TryInsertBatchError, TryRunScheduleError,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use alloc::{boxed::Box, vec::Vec};
|
use alloc::{boxed::Box, vec::Vec};
|
||||||
@ -694,7 +698,7 @@ impl World {
|
|||||||
|
|
||||||
match self.get_entity(entities) {
|
match self.get_entity(entities) {
|
||||||
Ok(fetched) => fetched,
|
Ok(fetched) => fetched,
|
||||||
Err(entity) => panic_no_entity(self, entity),
|
Err(error) => panic_no_entity(self, error.entity),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -821,7 +825,7 @@ impl World {
|
|||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
#[cold]
|
#[cold]
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn panic_on_err(e: EntityFetchError) -> ! {
|
fn panic_on_err(e: EntityMutableFetchError) -> ! {
|
||||||
panic!("{e}");
|
panic!("{e}");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -833,25 +837,23 @@ impl World {
|
|||||||
|
|
||||||
/// Returns the components of an [`Entity`] through [`ComponentInfo`].
|
/// Returns the components of an [`Entity`] through [`ComponentInfo`].
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn inspect_entity(&self, entity: Entity) -> impl Iterator<Item = &ComponentInfo> {
|
pub fn inspect_entity(
|
||||||
|
&self,
|
||||||
|
entity: Entity,
|
||||||
|
) -> Result<impl Iterator<Item = &ComponentInfo>, EntityDoesNotExistError> {
|
||||||
let entity_location = self
|
let entity_location = self
|
||||||
.entities()
|
.entities()
|
||||||
.get(entity)
|
.get(entity)
|
||||||
.unwrap_or_else(|| panic!("Entity {entity} does not exist"));
|
.ok_or(EntityDoesNotExistError::new(entity, self.entities()))?;
|
||||||
|
|
||||||
let archetype = self
|
let archetype = self
|
||||||
.archetypes()
|
.archetypes()
|
||||||
.get(entity_location.archetype_id)
|
.get(entity_location.archetype_id)
|
||||||
.unwrap_or_else(|| {
|
.expect("ArchetypeId was retrieved from an EntityLocation and should correspond to an Archetype");
|
||||||
panic!(
|
|
||||||
"Archetype {:?} does not exist",
|
|
||||||
entity_location.archetype_id
|
|
||||||
)
|
|
||||||
});
|
|
||||||
|
|
||||||
archetype
|
Ok(archetype
|
||||||
.components()
|
.components()
|
||||||
.filter_map(|id| self.components().get_info(id))
|
.filter_map(|id| self.components().get_info(id)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns [`EntityRef`]s that expose read-only operations for the given
|
/// Returns [`EntityRef`]s that expose read-only operations for the given
|
||||||
@ -869,7 +871,7 @@ impl World {
|
|||||||
/// # Errors
|
/// # Errors
|
||||||
///
|
///
|
||||||
/// If any of the given `entities` do not exist in the world, the first
|
/// If any of the given `entities` do not exist in the world, the first
|
||||||
/// [`Entity`] found to be missing will be returned in the [`Err`].
|
/// [`Entity`] found to be missing will return an [`EntityDoesNotExistError`].
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
@ -877,7 +879,10 @@ impl World {
|
|||||||
///
|
///
|
||||||
/// [`EntityHashSet`]: crate::entity::hash_set::EntityHashSet
|
/// [`EntityHashSet`]: crate::entity::hash_set::EntityHashSet
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_entity<F: WorldEntityFetch>(&self, entities: F) -> Result<F::Ref<'_>, Entity> {
|
pub fn get_entity<F: WorldEntityFetch>(
|
||||||
|
&self,
|
||||||
|
entities: F,
|
||||||
|
) -> Result<F::Ref<'_>, EntityDoesNotExistError> {
|
||||||
let cell = self.as_unsafe_world_cell_readonly();
|
let cell = self.as_unsafe_world_cell_readonly();
|
||||||
// SAFETY: `&self` gives read access to the entire world, and prevents mutable access.
|
// SAFETY: `&self` gives read access to the entire world, and prevents mutable access.
|
||||||
unsafe { entities.fetch_ref(cell) }
|
unsafe { entities.fetch_ref(cell) }
|
||||||
@ -905,9 +910,9 @@ impl World {
|
|||||||
///
|
///
|
||||||
/// # Errors
|
/// # Errors
|
||||||
///
|
///
|
||||||
/// - Returns [`EntityFetchError::NoSuchEntity`] if any of the given `entities` do not exist in the world.
|
/// - Returns [`EntityMutableFetchError::EntityDoesNotExist`] if any of the given `entities` do not exist in the world.
|
||||||
/// - Only the first entity found to be missing will be returned.
|
/// - Only the first entity found to be missing will be returned.
|
||||||
/// - Returns [`EntityFetchError::AliasedMutability`] if the same entity is requested multiple times.
|
/// - Returns [`EntityMutableFetchError::AliasedMutability`] if the same entity is requested multiple times.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
@ -918,7 +923,7 @@ impl World {
|
|||||||
pub fn get_entity_mut<F: WorldEntityFetch>(
|
pub fn get_entity_mut<F: WorldEntityFetch>(
|
||||||
&mut self,
|
&mut self,
|
||||||
entities: F,
|
entities: F,
|
||||||
) -> Result<F::Mut<'_>, EntityFetchError> {
|
) -> Result<F::Mut<'_>, EntityMutableFetchError> {
|
||||||
let cell = self.as_unsafe_world_cell();
|
let cell = self.as_unsafe_world_cell();
|
||||||
// SAFETY: `&mut self` gives mutable access to the entire world,
|
// SAFETY: `&mut self` gives mutable access to the entire world,
|
||||||
// and prevents any other access to the world.
|
// and prevents any other access to the world.
|
||||||
@ -1244,21 +1249,10 @@ impl World {
|
|||||||
&mut self,
|
&mut self,
|
||||||
entity: Entity,
|
entity: Entity,
|
||||||
f: impl FnOnce(&mut T) -> R,
|
f: impl FnOnce(&mut T) -> R,
|
||||||
) -> Result<Option<R>, EntityFetchError> {
|
) -> Result<Option<R>, EntityMutableFetchError> {
|
||||||
let mut world = DeferredWorld::from(&mut *self);
|
let mut world = DeferredWorld::from(&mut *self);
|
||||||
|
|
||||||
let result = match world.modify_component(entity, f) {
|
let result = world.modify_component(entity, f)?;
|
||||||
Ok(result) => result,
|
|
||||||
Err(EntityFetchError::AliasedMutability(..)) => {
|
|
||||||
return Err(EntityFetchError::AliasedMutability(entity))
|
|
||||||
}
|
|
||||||
Err(EntityFetchError::NoSuchEntity(..)) => {
|
|
||||||
return Err(EntityFetchError::NoSuchEntity(
|
|
||||||
entity,
|
|
||||||
self.entities().entity_does_not_exist_error_details(entity),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
self.flush();
|
self.flush();
|
||||||
Ok(result)
|
Ok(result)
|
||||||
@ -1304,7 +1298,7 @@ impl World {
|
|||||||
/// Despawns the given `entity`, if it exists. This will also remove all of the entity's
|
/// Despawns the given `entity`, if it exists. This will also remove all of the entity's
|
||||||
/// [`Components`](Component).
|
/// [`Components`](Component).
|
||||||
///
|
///
|
||||||
/// Returns a [`TryDespawnError`] if the entity does not exist.
|
/// Returns an [`EntityDespawnError`] if the entity does not exist.
|
||||||
///
|
///
|
||||||
/// # Note
|
/// # Note
|
||||||
///
|
///
|
||||||
@ -1312,7 +1306,7 @@ impl World {
|
|||||||
/// to despawn descendants. For example, this will recursively despawn [`Children`](crate::hierarchy::Children).
|
/// to despawn descendants. For example, this will recursively despawn [`Children`](crate::hierarchy::Children).
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn try_despawn(&mut self, entity: Entity) -> Result<(), TryDespawnError> {
|
pub fn try_despawn(&mut self, entity: Entity) -> Result<(), EntityDespawnError> {
|
||||||
self.despawn_with_caller(entity, MaybeLocation::caller())
|
self.despawn_with_caller(entity, MaybeLocation::caller())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1321,17 +1315,11 @@ impl World {
|
|||||||
&mut self,
|
&mut self,
|
||||||
entity: Entity,
|
entity: Entity,
|
||||||
caller: MaybeLocation,
|
caller: MaybeLocation,
|
||||||
) -> Result<(), TryDespawnError> {
|
) -> Result<(), EntityDespawnError> {
|
||||||
self.flush();
|
self.flush();
|
||||||
if let Ok(entity) = self.get_entity_mut(entity) {
|
let entity = self.get_entity_mut(entity)?;
|
||||||
entity.despawn_with_caller(caller);
|
entity.despawn_with_caller(caller);
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
|
||||||
Err(TryDespawnError {
|
|
||||||
entity,
|
|
||||||
details: self.entities().entity_does_not_exist_error_details(entity),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Clears the internal component tracker state.
|
/// Clears the internal component tracker state.
|
||||||
@ -3607,7 +3595,7 @@ mod tests {
|
|||||||
entity_disabling::{DefaultQueryFilters, Disabled},
|
entity_disabling::{DefaultQueryFilters, Disabled},
|
||||||
ptr::OwningPtr,
|
ptr::OwningPtr,
|
||||||
resource::Resource,
|
resource::Resource,
|
||||||
world::error::EntityFetchError,
|
world::error::EntityMutableFetchError,
|
||||||
};
|
};
|
||||||
use alloc::{
|
use alloc::{
|
||||||
borrow::ToOwned,
|
borrow::ToOwned,
|
||||||
@ -3992,39 +3980,39 @@ mod tests {
|
|||||||
let bar_id = TypeId::of::<Bar>();
|
let bar_id = TypeId::of::<Bar>();
|
||||||
let baz_id = TypeId::of::<Baz>();
|
let baz_id = TypeId::of::<Baz>();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
to_type_ids(world.inspect_entity(ent0).collect()),
|
to_type_ids(world.inspect_entity(ent0).unwrap().collect()),
|
||||||
[Some(foo_id), Some(bar_id), Some(baz_id)]
|
[Some(foo_id), Some(bar_id), Some(baz_id)]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect::<HashSet<_>>()
|
.collect::<HashSet<_>>()
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
to_type_ids(world.inspect_entity(ent1).collect()),
|
to_type_ids(world.inspect_entity(ent1).unwrap().collect()),
|
||||||
[Some(foo_id), Some(bar_id)]
|
[Some(foo_id), Some(bar_id)]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect::<HashSet<_>>()
|
.collect::<HashSet<_>>()
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
to_type_ids(world.inspect_entity(ent2).collect()),
|
to_type_ids(world.inspect_entity(ent2).unwrap().collect()),
|
||||||
[Some(bar_id), Some(baz_id)]
|
[Some(bar_id), Some(baz_id)]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect::<HashSet<_>>()
|
.collect::<HashSet<_>>()
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
to_type_ids(world.inspect_entity(ent3).collect()),
|
to_type_ids(world.inspect_entity(ent3).unwrap().collect()),
|
||||||
[Some(foo_id), Some(baz_id)]
|
[Some(foo_id), Some(baz_id)]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect::<HashSet<_>>()
|
.collect::<HashSet<_>>()
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
to_type_ids(world.inspect_entity(ent4).collect()),
|
to_type_ids(world.inspect_entity(ent4).unwrap().collect()),
|
||||||
[Some(foo_id)].into_iter().collect::<HashSet<_>>()
|
[Some(foo_id)].into_iter().collect::<HashSet<_>>()
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
to_type_ids(world.inspect_entity(ent5).collect()),
|
to_type_ids(world.inspect_entity(ent5).unwrap().collect()),
|
||||||
[Some(bar_id)].into_iter().collect::<HashSet<_>>()
|
[Some(bar_id)].into_iter().collect::<HashSet<_>>()
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
to_type_ids(world.inspect_entity(ent6).collect()),
|
to_type_ids(world.inspect_entity(ent6).unwrap().collect()),
|
||||||
[Some(baz_id)].into_iter().collect::<HashSet<_>>()
|
[Some(baz_id)].into_iter().collect::<HashSet<_>>()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -4171,20 +4159,34 @@ mod tests {
|
|||||||
|
|
||||||
world.entity_mut(e1).despawn();
|
world.entity_mut(e1).despawn();
|
||||||
|
|
||||||
assert_eq!(Err(e1), world.get_entity(e1).map(|_| {}));
|
assert_eq!(
|
||||||
assert_eq!(Err(e1), world.get_entity([e1, e2]).map(|_| {}));
|
Err(e1),
|
||||||
|
world.get_entity(e1).map(|_| {}).map_err(|e| e.entity)
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
Err(e1),
|
||||||
|
world.get_entity([e1, e2]).map(|_| {}).map_err(|e| e.entity)
|
||||||
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Err(e1),
|
Err(e1),
|
||||||
world
|
world
|
||||||
.get_entity(&[e1, e2] /* this is an array not a slice */)
|
.get_entity(&[e1, e2] /* this is an array not a slice */)
|
||||||
.map(|_| {})
|
.map(|_| {})
|
||||||
|
.map_err(|e| e.entity)
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
Err(e1),
|
||||||
|
world
|
||||||
|
.get_entity(&vec![e1, e2][..])
|
||||||
|
.map(|_| {})
|
||||||
|
.map_err(|e| e.entity)
|
||||||
);
|
);
|
||||||
assert_eq!(Err(e1), world.get_entity(&vec![e1, e2][..]).map(|_| {}));
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Err(e1),
|
Err(e1),
|
||||||
world
|
world
|
||||||
.get_entity(&EntityHashSet::from_iter([e1, e2]))
|
.get_entity(&EntityHashSet::from_iter([e1, e2]))
|
||||||
.map(|_| {})
|
.map(|_| {})
|
||||||
|
.map_err(|e| e.entity)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4206,17 +4208,17 @@ mod tests {
|
|||||||
.is_ok());
|
.is_ok());
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Err(EntityFetchError::AliasedMutability(e1)),
|
Err(EntityMutableFetchError::AliasedMutability(e1)),
|
||||||
world.get_entity_mut([e1, e2, e1]).map(|_| {})
|
world.get_entity_mut([e1, e2, e1]).map(|_| {})
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Err(EntityFetchError::AliasedMutability(e1)),
|
Err(EntityMutableFetchError::AliasedMutability(e1)),
|
||||||
world
|
world
|
||||||
.get_entity_mut(&[e1, e2, e1] /* this is an array not a slice */)
|
.get_entity_mut(&[e1, e2, e1] /* this is an array not a slice */)
|
||||||
.map(|_| {})
|
.map(|_| {})
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Err(EntityFetchError::AliasedMutability(e1)),
|
Err(EntityMutableFetchError::AliasedMutability(e1)),
|
||||||
world.get_entity_mut(&vec![e1, e2, e1][..]).map(|_| {})
|
world.get_entity_mut(&vec![e1, e2, e1][..]).map(|_| {})
|
||||||
);
|
);
|
||||||
// Aliased mutability isn't allowed by HashSets
|
// Aliased mutability isn't allowed by HashSets
|
||||||
@ -4228,25 +4230,25 @@ mod tests {
|
|||||||
|
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
world.get_entity_mut(e1).map(|_| {}),
|
world.get_entity_mut(e1).map(|_| {}),
|
||||||
Err(EntityFetchError::NoSuchEntity(e, ..)) if e == e1
|
Err(EntityMutableFetchError::EntityDoesNotExist(e)) if e.entity == e1
|
||||||
));
|
));
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
world.get_entity_mut([e1, e2]).map(|_| {}),
|
world.get_entity_mut([e1, e2]).map(|_| {}),
|
||||||
Err(EntityFetchError::NoSuchEntity(e,..)) if e == e1));
|
Err(EntityMutableFetchError::EntityDoesNotExist(e)) if e.entity == e1));
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
world
|
world
|
||||||
.get_entity_mut(&[e1, e2] /* this is an array not a slice */)
|
.get_entity_mut(&[e1, e2] /* this is an array not a slice */)
|
||||||
.map(|_| {}),
|
.map(|_| {}),
|
||||||
Err(EntityFetchError::NoSuchEntity(e, ..)) if e == e1));
|
Err(EntityMutableFetchError::EntityDoesNotExist(e)) if e.entity == e1));
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
world.get_entity_mut(&vec![e1, e2][..]).map(|_| {}),
|
world.get_entity_mut(&vec![e1, e2][..]).map(|_| {}),
|
||||||
Err(EntityFetchError::NoSuchEntity(e, ..)) if e == e1,
|
Err(EntityMutableFetchError::EntityDoesNotExist(e)) if e.entity == e1,
|
||||||
));
|
));
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
world
|
world
|
||||||
.get_entity_mut(&EntityHashSet::from_iter([e1, e2]))
|
.get_entity_mut(&EntityHashSet::from_iter([e1, e2]))
|
||||||
.map(|_| {}),
|
.map(|_| {}),
|
||||||
Err(EntityFetchError::NoSuchEntity(e, ..)) if e == e1));
|
Err(EntityMutableFetchError::EntityDoesNotExist(e)) if e.entity == e1));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@ -6,7 +6,7 @@ use crate::{
|
|||||||
bundle::Bundles,
|
bundle::Bundles,
|
||||||
change_detection::{MaybeLocation, MutUntyped, Ticks, TicksMut},
|
change_detection::{MaybeLocation, MutUntyped, Ticks, TicksMut},
|
||||||
component::{ComponentId, ComponentTicks, Components, Mutable, StorageType, Tick, TickCells},
|
component::{ComponentId, ComponentTicks, Components, Mutable, StorageType, Tick, TickCells},
|
||||||
entity::{Entities, Entity, EntityBorrow, EntityLocation},
|
entity::{Entities, Entity, EntityBorrow, EntityDoesNotExistError, EntityLocation},
|
||||||
observer::Observers,
|
observer::Observers,
|
||||||
prelude::Component,
|
prelude::Component,
|
||||||
query::{DebugCheckedUnwrap, ReadOnlyQueryData},
|
query::{DebugCheckedUnwrap, ReadOnlyQueryData},
|
||||||
@ -351,9 +351,15 @@ impl<'w> UnsafeWorldCell<'w> {
|
|||||||
/// Retrieves an [`UnsafeEntityCell`] that exposes read and write operations for the given `entity`.
|
/// Retrieves an [`UnsafeEntityCell`] that exposes read and write operations for the given `entity`.
|
||||||
/// Similar to the [`UnsafeWorldCell`], you are in charge of making sure that no aliasing rules are violated.
|
/// Similar to the [`UnsafeWorldCell`], you are in charge of making sure that no aliasing rules are violated.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_entity(self, entity: Entity) -> Option<UnsafeEntityCell<'w>> {
|
pub fn get_entity(
|
||||||
let location = self.entities().get(entity)?;
|
self,
|
||||||
Some(UnsafeEntityCell::new(self, entity, location))
|
entity: Entity,
|
||||||
|
) -> Result<UnsafeEntityCell<'w>, EntityDoesNotExistError> {
|
||||||
|
let location = self
|
||||||
|
.entities()
|
||||||
|
.get(entity)
|
||||||
|
.ok_or(EntityDoesNotExistError::new(entity, self.entities()))?;
|
||||||
|
Ok(UnsafeEntityCell::new(self, entity, location))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets a reference to the resource of the given type if it exists
|
/// Gets a reference to the resource of the given type if it exists
|
||||||
|
|||||||
@ -332,7 +332,9 @@ where
|
|||||||
let view = match self.view.get_manual(world, view) {
|
let view = match self.view.get_manual(world, view) {
|
||||||
Ok(view) => view,
|
Ok(view) => view,
|
||||||
Err(err) => match err {
|
Err(err) => match err {
|
||||||
QueryEntityError::NoSuchEntity(_, _) => return Err(DrawError::ViewEntityNotFound),
|
QueryEntityError::EntityDoesNotExist(_) => {
|
||||||
|
return Err(DrawError::ViewEntityNotFound)
|
||||||
|
}
|
||||||
QueryEntityError::QueryDoesNotMatch(_, _)
|
QueryEntityError::QueryDoesNotMatch(_, _)
|
||||||
| QueryEntityError::AliasedMutability(_) => {
|
| QueryEntityError::AliasedMutability(_) => {
|
||||||
return Err(DrawError::InvalidViewQuery)
|
return Err(DrawError::InvalidViewQuery)
|
||||||
|
|||||||
@ -52,11 +52,11 @@ fn map_error(err: QueryEntityError, ancestor: bool) -> ComputeGlobalTransformErr
|
|||||||
use ComputeGlobalTransformError::*;
|
use ComputeGlobalTransformError::*;
|
||||||
match err {
|
match err {
|
||||||
QueryEntityError::QueryDoesNotMatch(entity, _) => MissingTransform(entity),
|
QueryEntityError::QueryDoesNotMatch(entity, _) => MissingTransform(entity),
|
||||||
QueryEntityError::NoSuchEntity(entity, _) => {
|
QueryEntityError::EntityDoesNotExist(error) => {
|
||||||
if ancestor {
|
if ancestor {
|
||||||
MalformedHierarchy(entity)
|
MalformedHierarchy(error.entity)
|
||||||
} else {
|
} else {
|
||||||
NoSuchEntity(entity)
|
NoSuchEntity(error.entity)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
QueryEntityError::AliasedMutability(_) => unreachable!(),
|
QueryEntityError::AliasedMutability(_) => unreachable!(),
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user