added back get_entity
it's not exact, but it should be good enough.
This commit is contained in:
parent
7b044c0908
commit
5c582666be
@ -782,6 +782,14 @@ impl Entities {
|
|||||||
.map(|meta| meta.location)
|
.map(|meta| meta.location)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns true if the entity exists in the world *now*:
|
||||||
|
/// It has a location, etc.
|
||||||
|
///
|
||||||
|
/// This will return false if the `entity` is reserved but has not been constructed.
|
||||||
|
pub fn contains(&self, entity: Entity) -> bool {
|
||||||
|
self.get(entity).is_some()
|
||||||
|
}
|
||||||
|
|
||||||
/// Provides information regarding if `entity` may be constructed.
|
/// Provides information regarding if `entity` may be constructed.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn validate_construction(&self, entity: Entity) -> Result<(), ConstructionError> {
|
pub fn validate_construction(&self, entity: Entity) -> Result<(), ConstructionError> {
|
||||||
|
@ -18,7 +18,7 @@ use crate::{
|
|||||||
bundle::{Bundle, InsertMode, NoBundleEffect},
|
bundle::{Bundle, InsertMode, NoBundleEffect},
|
||||||
change_detection::{MaybeLocation, Mut},
|
change_detection::{MaybeLocation, Mut},
|
||||||
component::{Component, ComponentId, Mutable},
|
component::{Component, ComponentId, Mutable},
|
||||||
entity::{Entities, EntitiesAllocator, Entity, EntityClonerBuilder},
|
entity::{Entities, EntitiesAllocator, Entity, EntityClonerBuilder, EntityDoesNotExistError},
|
||||||
error::{ignore, warn, BevyError, CommandWithEntity, ErrorContext, HandleError},
|
error::{ignore, warn, BevyError, CommandWithEntity, ErrorContext, HandleError},
|
||||||
event::Event,
|
event::Event,
|
||||||
observer::{Observer, TriggerTargets},
|
observer::{Observer, TriggerTargets},
|
||||||
@ -99,7 +99,8 @@ use crate::{
|
|||||||
/// [`ApplyDeferred`]: crate::schedule::ApplyDeferred
|
/// [`ApplyDeferred`]: crate::schedule::ApplyDeferred
|
||||||
pub struct Commands<'w, 's> {
|
pub struct Commands<'w, 's> {
|
||||||
queue: InternalQueue<'s>,
|
queue: InternalQueue<'s>,
|
||||||
entities: &'w EntitiesAllocator,
|
entities: &'w Entities,
|
||||||
|
allocator: &'w EntitiesAllocator,
|
||||||
}
|
}
|
||||||
|
|
||||||
// SAFETY: All commands [`Command`] implement [`Send`]
|
// SAFETY: All commands [`Command`] implement [`Send`]
|
||||||
@ -109,7 +110,11 @@ unsafe impl Send for Commands<'_, '_> {}
|
|||||||
unsafe impl Sync for Commands<'_, '_> {}
|
unsafe impl Sync for Commands<'_, '_> {}
|
||||||
|
|
||||||
const _: () = {
|
const _: () = {
|
||||||
type __StructFieldsAlias<'w, 's> = (Deferred<'s, CommandQueue>, &'w Entities);
|
type __StructFieldsAlias<'w, 's> = (
|
||||||
|
Deferred<'s, CommandQueue>,
|
||||||
|
&'w EntitiesAllocator,
|
||||||
|
&'w Entities,
|
||||||
|
);
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub struct FetchState {
|
pub struct FetchState {
|
||||||
state: <__StructFieldsAlias<'static, 'static> as bevy_ecs::system::SystemParam>::State,
|
state: <__StructFieldsAlias<'static, 'static> as bevy_ecs::system::SystemParam>::State,
|
||||||
@ -162,7 +167,7 @@ const _: () = {
|
|||||||
system_meta: &bevy_ecs::system::SystemMeta,
|
system_meta: &bevy_ecs::system::SystemMeta,
|
||||||
world: UnsafeWorldCell,
|
world: UnsafeWorldCell,
|
||||||
) -> Result<(), SystemParamValidationError> {
|
) -> Result<(), SystemParamValidationError> {
|
||||||
<(Deferred<CommandQueue>, &Entities) as bevy_ecs::system::SystemParam>::validate_param(
|
<__StructFieldsAlias as bevy_ecs::system::SystemParam>::validate_param(
|
||||||
&mut state.state,
|
&mut state.state,
|
||||||
system_meta,
|
system_meta,
|
||||||
world,
|
world,
|
||||||
@ -176,10 +181,16 @@ const _: () = {
|
|||||||
world: UnsafeWorldCell<'w>,
|
world: UnsafeWorldCell<'w>,
|
||||||
change_tick: bevy_ecs::component::Tick,
|
change_tick: bevy_ecs::component::Tick,
|
||||||
) -> Self::Item<'w, 's> {
|
) -> Self::Item<'w, 's> {
|
||||||
let(f0, f1) = <(Deferred<'s, CommandQueue>, &'w EntitiesAllocator) as bevy_ecs::system::SystemParam>::get_param(&mut state.state, system_meta, world, change_tick);
|
let params = <__StructFieldsAlias as bevy_ecs::system::SystemParam>::get_param(
|
||||||
|
&mut state.state,
|
||||||
|
system_meta,
|
||||||
|
world,
|
||||||
|
change_tick,
|
||||||
|
);
|
||||||
Commands {
|
Commands {
|
||||||
queue: InternalQueue::CommandQueue(f0),
|
queue: InternalQueue::CommandQueue(params.0),
|
||||||
entities: f1,
|
allocator: params.1,
|
||||||
|
entities: params.2,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -200,13 +211,18 @@ enum InternalQueue<'s> {
|
|||||||
impl<'w, 's> Commands<'w, 's> {
|
impl<'w, 's> Commands<'w, 's> {
|
||||||
/// Returns a new `Commands` instance from a [`CommandQueue`] and a [`World`].
|
/// Returns a new `Commands` instance from a [`CommandQueue`] and a [`World`].
|
||||||
pub fn new(queue: &'s mut CommandQueue, world: &'w World) -> Self {
|
pub fn new(queue: &'s mut CommandQueue, world: &'w World) -> Self {
|
||||||
Self::new_from_entities(queue, &world.allocator)
|
Self::new_from_entities(queue, &world.allocator, &world.entities)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a new `Commands` instance from a [`CommandQueue`] and an [`Entities`] reference.
|
/// Returns a new `Commands` instance from a [`CommandQueue`] and an [`Entities`] reference.
|
||||||
pub fn new_from_entities(queue: &'s mut CommandQueue, entities: &'w EntitiesAllocator) -> Self {
|
pub fn new_from_entities(
|
||||||
|
queue: &'s mut CommandQueue,
|
||||||
|
allocator: &'w EntitiesAllocator,
|
||||||
|
entities: &'w Entities,
|
||||||
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
queue: InternalQueue::CommandQueue(Deferred(queue)),
|
queue: InternalQueue::CommandQueue(Deferred(queue)),
|
||||||
|
allocator,
|
||||||
entities,
|
entities,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -220,10 +236,12 @@ impl<'w, 's> Commands<'w, 's> {
|
|||||||
/// * Caller ensures that `queue` must outlive `'w`
|
/// * Caller ensures that `queue` must outlive `'w`
|
||||||
pub(crate) unsafe fn new_raw_from_entities(
|
pub(crate) unsafe fn new_raw_from_entities(
|
||||||
queue: RawCommandQueue,
|
queue: RawCommandQueue,
|
||||||
entities: &'w EntitiesAllocator,
|
allocator: &'w EntitiesAllocator,
|
||||||
|
entities: &'w Entities,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
queue: InternalQueue::RawCommandQueue(queue),
|
queue: InternalQueue::RawCommandQueue(queue),
|
||||||
|
allocator,
|
||||||
entities,
|
entities,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -255,6 +273,7 @@ impl<'w, 's> Commands<'w, 's> {
|
|||||||
InternalQueue::RawCommandQueue(queue.clone())
|
InternalQueue::RawCommandQueue(queue.clone())
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
allocator: self.allocator,
|
||||||
entities: self.entities,
|
entities: self.entities,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -304,7 +323,7 @@ impl<'w, 's> Commands<'w, 's> {
|
|||||||
/// with the same combination of components.
|
/// with the same combination of components.
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
pub fn spawn_empty(&mut self) -> EntityCommands {
|
pub fn spawn_empty(&mut self) -> EntityCommands {
|
||||||
let entity = self.entities.alloc();
|
let entity = self.allocator.alloc();
|
||||||
let caller = MaybeLocation::caller();
|
let caller = MaybeLocation::caller();
|
||||||
self.queue(move |world: &mut World| {
|
self.queue(move |world: &mut World| {
|
||||||
world
|
world
|
||||||
@ -358,7 +377,7 @@ impl<'w, 's> Commands<'w, 's> {
|
|||||||
/// with the same combination of components.
|
/// with the same combination of components.
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
pub fn spawn<T: Bundle>(&mut self, bundle: T) -> EntityCommands {
|
pub fn spawn<T: Bundle>(&mut self, bundle: T) -> EntityCommands {
|
||||||
let entity = self.entities.alloc();
|
let entity = self.allocator.alloc();
|
||||||
let caller = MaybeLocation::caller();
|
let caller = MaybeLocation::caller();
|
||||||
self.queue(move |world: &mut World| {
|
self.queue(move |world: &mut World| {
|
||||||
world
|
world
|
||||||
@ -404,6 +423,62 @@ impl<'w, 's> Commands<'w, 's> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the [`EntityCommands`] for the requested [`Entity`] if it exists in the world *now*.
|
||||||
|
/// Note that for entities that have not been constructed, like ones from [`spawn`](Self::spawn), this will error.
|
||||||
|
///
|
||||||
|
/// This method does not guarantee that commands queued by the returned `EntityCommands`
|
||||||
|
/// will be successful, since the entity could be despawned before they are executed.
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
///
|
||||||
|
/// Returns [`EntityDoesNotExistError`] if the requested entity does not exist.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use bevy_ecs::prelude::*;
|
||||||
|
/// #[derive(Resource)]
|
||||||
|
/// struct PlayerEntity {
|
||||||
|
/// entity: Entity
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// #[derive(Component)]
|
||||||
|
/// struct Label(&'static str);
|
||||||
|
///
|
||||||
|
/// fn example_system(mut commands: Commands, player: Res<PlayerEntity>) -> Result {
|
||||||
|
/// // Get the entity if it still exists and store the `EntityCommands`.
|
||||||
|
/// // If it doesn't exist, the `?` operator will propagate the returned error
|
||||||
|
/// // to the system, and the system will pass it to an error handler.
|
||||||
|
/// let mut entity_commands = commands.get_entity(player.entity)?;
|
||||||
|
///
|
||||||
|
/// // Add a component to the entity.
|
||||||
|
/// entity_commands.insert(Label("hello world"));
|
||||||
|
///
|
||||||
|
/// // Return from the system successfully.
|
||||||
|
/// Ok(())
|
||||||
|
/// }
|
||||||
|
/// # bevy_ecs::system::assert_is_system(example_system);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// # See also
|
||||||
|
///
|
||||||
|
/// - [`entity`](Self::entity) for the infallible version.
|
||||||
|
#[inline]
|
||||||
|
#[track_caller]
|
||||||
|
pub fn get_entity(
|
||||||
|
&mut self,
|
||||||
|
entity: Entity,
|
||||||
|
) -> Result<EntityCommands, EntityDoesNotExistError> {
|
||||||
|
if self.entities.contains(entity) {
|
||||||
|
Ok(EntityCommands {
|
||||||
|
entity,
|
||||||
|
commands: self.reborrow(),
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
Err(EntityDoesNotExistError::new(entity, self.entities))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Spawns multiple entities with the same combination of components,
|
/// Spawns multiple entities with the same combination of components,
|
||||||
/// based on a batch of [`Bundles`](Bundle).
|
/// based on a batch of [`Bundles`](Bundle).
|
||||||
///
|
///
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use bevy_utils::Parallel;
|
use bevy_utils::Parallel;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
entity::EntitiesAllocator,
|
entity::{Entities, EntitiesAllocator},
|
||||||
prelude::World,
|
prelude::World,
|
||||||
system::{Deferred, SystemBuffer, SystemMeta, SystemParam},
|
system::{Deferred, SystemBuffer, SystemMeta, SystemParam},
|
||||||
};
|
};
|
||||||
@ -51,7 +51,8 @@ struct ParallelCommandQueue {
|
|||||||
#[derive(SystemParam)]
|
#[derive(SystemParam)]
|
||||||
pub struct ParallelCommands<'w, 's> {
|
pub struct ParallelCommands<'w, 's> {
|
||||||
state: Deferred<'s, ParallelCommandQueue>,
|
state: Deferred<'s, ParallelCommandQueue>,
|
||||||
entities: &'w EntitiesAllocator,
|
allocator: &'w EntitiesAllocator,
|
||||||
|
entities: &'w Entities,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SystemBuffer for ParallelCommandQueue {
|
impl SystemBuffer for ParallelCommandQueue {
|
||||||
@ -71,7 +72,7 @@ impl<'w, 's> ParallelCommands<'w, 's> {
|
|||||||
/// For an example, see the type-level documentation for [`ParallelCommands`].
|
/// For an example, see the type-level documentation for [`ParallelCommands`].
|
||||||
pub fn command_scope<R>(&self, f: impl FnOnce(Commands) -> R) -> R {
|
pub fn command_scope<R>(&self, f: impl FnOnce(Commands) -> R) -> R {
|
||||||
self.state.thread_queues.scope(|queue| {
|
self.state.thread_queues.scope(|queue| {
|
||||||
let commands = Commands::new_from_entities(queue, self.entities);
|
let commands = Commands::new_from_entities(queue, self.allocator, self.entities);
|
||||||
f(commands)
|
f(commands)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -69,7 +69,13 @@ impl<'w> DeferredWorld<'w> {
|
|||||||
// SAFETY: &mut self ensure that there are no outstanding accesses to the queue
|
// SAFETY: &mut self ensure that there are no outstanding accesses to the queue
|
||||||
let command_queue = unsafe { self.world.get_raw_command_queue() };
|
let command_queue = unsafe { self.world.get_raw_command_queue() };
|
||||||
// SAFETY: command_queue is stored on world and always valid while the world exists
|
// SAFETY: command_queue is stored on world and always valid while the world exists
|
||||||
unsafe { Commands::new_raw_from_entities(command_queue, self.world.entities_allocator()) }
|
unsafe {
|
||||||
|
Commands::new_raw_from_entities(
|
||||||
|
command_queue,
|
||||||
|
self.world.entities_allocator(),
|
||||||
|
self.world.entities(),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieves a mutable reference to the given `entity`'s [`Component`] of the given type.
|
/// Retrieves a mutable reference to the given `entity`'s [`Component`] of the given type.
|
||||||
@ -415,8 +421,9 @@ impl<'w> DeferredWorld<'w> {
|
|||||||
// - Command queue access does not conflict with entity access.
|
// - Command queue access does not conflict with entity access.
|
||||||
let raw_queue = unsafe { cell.get_raw_command_queue() };
|
let raw_queue = unsafe { cell.get_raw_command_queue() };
|
||||||
// SAFETY: `&mut self` ensures the commands does not outlive the world.
|
// SAFETY: `&mut self` ensures the commands does not outlive the world.
|
||||||
let commands =
|
let commands = unsafe {
|
||||||
unsafe { Commands::new_raw_from_entities(raw_queue, cell.entities_allocator()) };
|
Commands::new_raw_from_entities(raw_queue, cell.entities_allocator(), cell.entities())
|
||||||
|
};
|
||||||
|
|
||||||
(fetcher, commands)
|
(fetcher, commands)
|
||||||
}
|
}
|
||||||
|
@ -267,7 +267,13 @@ impl World {
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn commands(&mut self) -> Commands {
|
pub fn commands(&mut self) -> Commands {
|
||||||
// SAFETY: command_queue is stored on world and always valid while the world exists
|
// SAFETY: command_queue is stored on world and always valid while the world exists
|
||||||
unsafe { Commands::new_raw_from_entities(self.command_queue.clone(), &self.allocator) }
|
unsafe {
|
||||||
|
Commands::new_raw_from_entities(
|
||||||
|
self.command_queue.clone(),
|
||||||
|
&self.allocator,
|
||||||
|
&self.entities,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Registers a new [`Component`] type and returns the [`ComponentId`] created for it.
|
/// Registers a new [`Component`] type and returns the [`ComponentId`] created for it.
|
||||||
@ -1046,8 +1052,9 @@ impl World {
|
|||||||
// - Command queue access does not conflict with entity access.
|
// - Command queue access does not conflict with entity access.
|
||||||
let raw_queue = unsafe { cell.get_raw_command_queue() };
|
let raw_queue = unsafe { cell.get_raw_command_queue() };
|
||||||
// SAFETY: `&mut self` ensures the commands does not outlive the world.
|
// SAFETY: `&mut self` ensures the commands does not outlive the world.
|
||||||
let commands =
|
let commands = unsafe {
|
||||||
unsafe { Commands::new_raw_from_entities(raw_queue, cell.entities_allocator()) };
|
Commands::new_raw_from_entities(raw_queue, cell.entities_allocator(), cell.entities())
|
||||||
|
};
|
||||||
|
|
||||||
(fetcher, commands)
|
(fetcher, commands)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user