-
-
Notifications
You must be signed in to change notification settings - Fork 4.1k
implement get_many_unique #18315
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
implement get_many_unique #18315
Changes from 6 commits
e1b1439
a2f9630
5e6e71c
70ba56b
f5c4c9c
b6f4c6a
6993690
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
use crate::{ | ||
archetype::{Archetype, ArchetypeComponentId, ArchetypeGeneration, ArchetypeId}, | ||
component::{ComponentId, Tick}, | ||
entity::{Entity, EntityBorrow, EntitySet}, | ||
entity::{unique_array::UniqueEntityArray, Entity, EntityBorrow, EntitySet}, | ||
entity_disabling::DefaultQueryFilters, | ||
prelude::FromWorld, | ||
query::{Access, FilteredAccess, QueryCombinationIter, QueryIter, QueryParIter, WorldQuery}, | ||
|
@@ -997,6 +997,44 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> { | |
self.query(world).get_many_inner(entities) | ||
} | ||
|
||
/// Returns the read-only query results for the given [`UniqueEntityArray`]. | ||
/// | ||
/// In case of a nonexisting entity or mismatched component, a [`QueryEntityError`] is | ||
/// returned instead. | ||
/// | ||
/// # Examples | ||
/// | ||
/// ``` | ||
/// use bevy_ecs::{prelude::*, query::QueryEntityError, entity::{EntitySetIterator, unique_array::UniqueEntityArray, unique_vec::UniqueEntityVec}}; | ||
/// | ||
/// #[derive(Component, PartialEq, Debug)] | ||
/// struct A(usize); | ||
/// | ||
/// let mut world = World::new(); | ||
/// let entity_set: UniqueEntityVec = world.spawn_batch((0..3).map(A)).collect_set(); | ||
/// let entity_set: UniqueEntityArray<3> = entity_set.try_into().unwrap(); | ||
/// | ||
/// world.spawn(A(73)); | ||
/// | ||
/// let mut query_state = world.query::<&A>(); | ||
/// | ||
/// let component_values = query_state.get_many_unique(&world, entity_set).unwrap(); | ||
/// | ||
/// assert_eq!(component_values, [&A(0), &A(1), &A(2)]); | ||
/// | ||
/// let wrong_entity = Entity::from_raw(365); | ||
/// | ||
/// assert_eq!(match query_state.get_many_unique(&mut world, UniqueEntityArray::from([wrong_entity])).unwrap_err() {QueryEntityError::EntityDoesNotExist(error) => error.entity, _ => panic!()}, wrong_entity); | ||
/// ``` | ||
#[inline] | ||
pub fn get_many_unique<'w, const N: usize>( | ||
&mut self, | ||
world: &'w World, | ||
entities: UniqueEntityArray<N, Entity>, | ||
Victoronz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
) -> Result<[ROQueryItem<'w, D>; N], QueryEntityError> { | ||
self.query(world).get_many_unique_inner(entities) | ||
} | ||
|
||
/// Gets the query result for the given [`World`] and [`Entity`]. | ||
/// | ||
/// This is always guaranteed to run in `O(1)` time. | ||
|
@@ -1053,7 +1091,52 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> { | |
world: &'w mut World, | ||
entities: [Entity; N], | ||
) -> Result<[D::Item<'w>; N], QueryEntityError> { | ||
self.query_mut(world).get_many_inner(entities) | ||
self.query_mut(world).get_many_mut_inner(entities) | ||
} | ||
|
||
/// Returns the query results for the given [`UniqueEntityArray`]. | ||
/// | ||
/// In case of a nonexisting entity or mismatched component, a [`QueryEntityError`] is | ||
/// returned instead. | ||
/// | ||
/// ``` | ||
/// use bevy_ecs::{prelude::*, query::QueryEntityError, entity::{EntitySetIterator, unique_array::UniqueEntityArray, unique_vec::UniqueEntityVec}}; | ||
/// | ||
/// #[derive(Component, PartialEq, Debug)] | ||
/// struct A(usize); | ||
/// | ||
/// let mut world = World::new(); | ||
/// | ||
/// let entity_set: UniqueEntityVec = world.spawn_batch((0..3).map(A)).collect_set(); | ||
/// let entity_set: UniqueEntityArray<3> = entity_set.try_into().unwrap(); | ||
/// | ||
/// world.spawn(A(73)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You are spawning an entity here with component There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have copied and adjusted the existing doc tests for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Cool beans! I think that an example that showcases this functionality would be good then cause you could comment why Totally not blocking tho! |
||
/// | ||
/// let mut query_state = world.query::<&mut A>(); | ||
/// | ||
/// let mut mutable_component_values = query_state.get_many_unique_mut(&mut world, entity_set).unwrap(); | ||
/// | ||
/// for mut a in &mut mutable_component_values { | ||
/// a.0 += 5; | ||
/// } | ||
/// | ||
/// let component_values = query_state.get_many_unique(&world, entity_set).unwrap(); | ||
/// | ||
/// assert_eq!(component_values, [&A(5), &A(6), &A(7)]); | ||
/// | ||
/// let wrong_entity = Entity::from_raw(57); | ||
/// let invalid_entity = world.spawn_empty().id(); | ||
/// | ||
/// assert_eq!(match query_state.get_many_unique(&mut world, UniqueEntityArray::from([wrong_entity])).unwrap_err() {QueryEntityError::EntityDoesNotExist(error) => error.entity, _ => panic!()}, wrong_entity); | ||
/// assert_eq!(match query_state.get_many_unique_mut(&mut world, UniqueEntityArray::from([invalid_entity])).unwrap_err() {QueryEntityError::QueryDoesNotMatch(entity, _) => entity, _ => panic!()}, invalid_entity); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is the reason this is returning an error because you expect every entity to have component 'A'? If so, why not just return an empty list of components? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These asserts test that the error cases are produced properly. |
||
/// ``` | ||
#[inline] | ||
pub fn get_many_unique_mut<'w, const N: usize>( | ||
&mut self, | ||
world: &'w mut World, | ||
entities: UniqueEntityArray<N, Entity>, | ||
Victoronz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
) -> Result<[D::Item<'w>; N], QueryEntityError> { | ||
self.query_mut(world).get_many_unique_inner(entities) | ||
} | ||
|
||
/// Gets the query result for the given [`World`] and [`Entity`]. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm hoping to deprecate the methods like this on
QueryState
, so I'd mildly prefer not to add these in the first place. The functionality would still be available as.query(world).get_many_unique_inner(entities)
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I was a little confused why this function needed to be implemented for both the state module and query module. It seems like it would only really be needed in the query module
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For context: Until recently, the actual implementation of all of these methods was on
QueryState
, and theQuery
methods just called those. I added theQueryState::query
methods and moved the implementations over, with the eventual goal of getting rid of most of the other methods onQueryState
.Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am aware that we're trying to deprecate them!
However in the spirit of being incremental, I find it more confusing to not add them here when the other methods do not yet have the
#[deprecated]
moniker. Once we do deprecate them before 0.16, then feel free to remove these again!Given that sometimes PRs can miss a cut-off, or contributors don't have time before an RC/release, leaving changes unfinished seems like an uneccessary risk, when both adding and removing is simple implementation-wise.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, in that case, you forgot
get_many_unique_manual(&self, &World, entities)
andget_many_unique_unchecked(&mut self, UnsafeWorldCell, entities)
:PThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These already don't exist for
get_many
, so I haven't added them here.These inconsistencies are not nice, but we can at least not make them worse in the interim :P