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)
|
||||
}
|
||||
|
||||
/// 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.
|
||||
#[inline]
|
||||
pub fn validate_construction(&self, entity: Entity) -> Result<(), ConstructionError> {
|
||||
|
@ -18,7 +18,7 @@ use crate::{
|
||||
bundle::{Bundle, InsertMode, NoBundleEffect},
|
||||
change_detection::{MaybeLocation, Mut},
|
||||
component::{Component, ComponentId, Mutable},
|
||||
entity::{Entities, EntitiesAllocator, Entity, EntityClonerBuilder},
|
||||
entity::{Entities, EntitiesAllocator, Entity, EntityClonerBuilder, EntityDoesNotExistError},
|
||||
error::{ignore, warn, BevyError, CommandWithEntity, ErrorContext, HandleError},
|
||||
event::Event,
|
||||
observer::{Observer, TriggerTargets},
|
||||
@ -99,7 +99,8 @@ use crate::{
|
||||
/// [`ApplyDeferred`]: crate::schedule::ApplyDeferred
|
||||
pub struct Commands<'w, 's> {
|
||||
queue: InternalQueue<'s>,
|
||||
entities: &'w EntitiesAllocator,
|
||||
entities: &'w Entities,
|
||||
allocator: &'w EntitiesAllocator,
|
||||
}
|
||||
|
||||
// SAFETY: All commands [`Command`] implement [`Send`]
|
||||
@ -109,7 +110,11 @@ unsafe impl Send for Commands<'_, '_> {}
|
||||
unsafe impl Sync for Commands<'_, '_> {}
|
||||
|
||||
const _: () = {
|
||||
type __StructFieldsAlias<'w, 's> = (Deferred<'s, CommandQueue>, &'w Entities);
|
||||
type __StructFieldsAlias<'w, 's> = (
|
||||
Deferred<'s, CommandQueue>,
|
||||
&'w EntitiesAllocator,
|
||||
&'w Entities,
|
||||
);
|
||||
#[doc(hidden)]
|
||||
pub struct FetchState {
|
||||
state: <__StructFieldsAlias<'static, 'static> as bevy_ecs::system::SystemParam>::State,
|
||||
@ -162,7 +167,7 @@ const _: () = {
|
||||
system_meta: &bevy_ecs::system::SystemMeta,
|
||||
world: UnsafeWorldCell,
|
||||
) -> Result<(), SystemParamValidationError> {
|
||||
<(Deferred<CommandQueue>, &Entities) as bevy_ecs::system::SystemParam>::validate_param(
|
||||
<__StructFieldsAlias as bevy_ecs::system::SystemParam>::validate_param(
|
||||
&mut state.state,
|
||||
system_meta,
|
||||
world,
|
||||
@ -176,10 +181,16 @@ const _: () = {
|
||||
world: UnsafeWorldCell<'w>,
|
||||
change_tick: bevy_ecs::component::Tick,
|
||||
) -> 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 {
|
||||
queue: InternalQueue::CommandQueue(f0),
|
||||
entities: f1,
|
||||
queue: InternalQueue::CommandQueue(params.0),
|
||||
allocator: params.1,
|
||||
entities: params.2,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -200,13 +211,18 @@ enum InternalQueue<'s> {
|
||||
impl<'w, 's> Commands<'w, 's> {
|
||||
/// Returns a new `Commands` instance from a [`CommandQueue`] and a [`World`].
|
||||
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.
|
||||
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 {
|
||||
queue: InternalQueue::CommandQueue(Deferred(queue)),
|
||||
allocator,
|
||||
entities,
|
||||
}
|
||||
}
|
||||
@ -220,10 +236,12 @@ impl<'w, 's> Commands<'w, 's> {
|
||||
/// * Caller ensures that `queue` must outlive `'w`
|
||||
pub(crate) unsafe fn new_raw_from_entities(
|
||||
queue: RawCommandQueue,
|
||||
entities: &'w EntitiesAllocator,
|
||||
allocator: &'w EntitiesAllocator,
|
||||
entities: &'w Entities,
|
||||
) -> Self {
|
||||
Self {
|
||||
queue: InternalQueue::RawCommandQueue(queue),
|
||||
allocator,
|
||||
entities,
|
||||
}
|
||||
}
|
||||
@ -255,6 +273,7 @@ impl<'w, 's> Commands<'w, 's> {
|
||||
InternalQueue::RawCommandQueue(queue.clone())
|
||||
}
|
||||
},
|
||||
allocator: self.allocator,
|
||||
entities: self.entities,
|
||||
}
|
||||
}
|
||||
@ -304,7 +323,7 @@ impl<'w, 's> Commands<'w, 's> {
|
||||
/// with the same combination of components.
|
||||
#[track_caller]
|
||||
pub fn spawn_empty(&mut self) -> EntityCommands {
|
||||
let entity = self.entities.alloc();
|
||||
let entity = self.allocator.alloc();
|
||||
let caller = MaybeLocation::caller();
|
||||
self.queue(move |world: &mut World| {
|
||||
world
|
||||
@ -358,7 +377,7 @@ impl<'w, 's> Commands<'w, 's> {
|
||||
/// with the same combination of components.
|
||||
#[track_caller]
|
||||
pub fn spawn<T: Bundle>(&mut self, bundle: T) -> EntityCommands {
|
||||
let entity = self.entities.alloc();
|
||||
let entity = self.allocator.alloc();
|
||||
let caller = MaybeLocation::caller();
|
||||
self.queue(move |world: &mut 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,
|
||||
/// based on a batch of [`Bundles`](Bundle).
|
||||
///
|
||||
|
@ -1,7 +1,7 @@
|
||||
use bevy_utils::Parallel;
|
||||
|
||||
use crate::{
|
||||
entity::EntitiesAllocator,
|
||||
entity::{Entities, EntitiesAllocator},
|
||||
prelude::World,
|
||||
system::{Deferred, SystemBuffer, SystemMeta, SystemParam},
|
||||
};
|
||||
@ -51,7 +51,8 @@ struct ParallelCommandQueue {
|
||||
#[derive(SystemParam)]
|
||||
pub struct ParallelCommands<'w, 's> {
|
||||
state: Deferred<'s, ParallelCommandQueue>,
|
||||
entities: &'w EntitiesAllocator,
|
||||
allocator: &'w EntitiesAllocator,
|
||||
entities: &'w Entities,
|
||||
}
|
||||
|
||||
impl SystemBuffer for ParallelCommandQueue {
|
||||
@ -71,7 +72,7 @@ impl<'w, 's> ParallelCommands<'w, 's> {
|
||||
/// For an example, see the type-level documentation for [`ParallelCommands`].
|
||||
pub fn command_scope<R>(&self, f: impl FnOnce(Commands) -> R) -> R {
|
||||
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)
|
||||
})
|
||||
}
|
||||
|
@ -69,7 +69,13 @@ impl<'w> DeferredWorld<'w> {
|
||||
// SAFETY: &mut self ensure that there are no outstanding accesses to the 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
|
||||
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.
|
||||
@ -415,8 +421,9 @@ impl<'w> DeferredWorld<'w> {
|
||||
// - Command queue access does not conflict with entity access.
|
||||
let raw_queue = unsafe { cell.get_raw_command_queue() };
|
||||
// SAFETY: `&mut self` ensures the commands does not outlive the world.
|
||||
let commands =
|
||||
unsafe { Commands::new_raw_from_entities(raw_queue, cell.entities_allocator()) };
|
||||
let commands = unsafe {
|
||||
Commands::new_raw_from_entities(raw_queue, cell.entities_allocator(), cell.entities())
|
||||
};
|
||||
|
||||
(fetcher, commands)
|
||||
}
|
||||
|
@ -267,7 +267,13 @@ impl World {
|
||||
#[inline]
|
||||
pub fn commands(&mut self) -> Commands {
|
||||
// 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.
|
||||
@ -1046,8 +1052,9 @@ impl World {
|
||||
// - Command queue access does not conflict with entity access.
|
||||
let raw_queue = unsafe { cell.get_raw_command_queue() };
|
||||
// SAFETY: `&mut self` ensures the commands does not outlive the world.
|
||||
let commands =
|
||||
unsafe { Commands::new_raw_from_entities(raw_queue, cell.entities_allocator()) };
|
||||
let commands = unsafe {
|
||||
Commands::new_raw_from_entities(raw_queue, cell.entities_allocator(), cell.entities())
|
||||
};
|
||||
|
||||
(fetcher, commands)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user