-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Implement WorldQuery for EntityRef #6960
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
Changes from all commits
e9fc9d0
13387e3
c74843c
d00da4e
9cd5baa
ddd845f
a94a348
fc4a1c6
185310b
aea7f0b
a0cbc4b
39cf337
0c91c16
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 |
---|---|---|
|
@@ -5,7 +5,7 @@ use crate::{ | |
entity::Entity, | ||
query::{Access, DebugCheckedUnwrap, FilteredAccess}, | ||
storage::{ComponentSparseSet, Table, TableRow}, | ||
world::{unsafe_world_cell::UnsafeWorldCell, Mut, Ref, World}, | ||
world::{unsafe_world_cell::UnsafeWorldCell, EntityRef, Mut, Ref, World}, | ||
}; | ||
pub use bevy_ecs_macros::WorldQuery; | ||
use bevy_ptr::{ThinSlicePtr, UnsafeCellDeref}; | ||
|
@@ -536,6 +536,89 @@ unsafe impl WorldQuery for Entity { | |
/// SAFETY: access is read only | ||
unsafe impl ReadOnlyWorldQuery for Entity {} | ||
|
||
/// SAFETY: `Self` is the same as `Self::ReadOnly` | ||
unsafe impl<'a> WorldQuery for EntityRef<'a> { | ||
type Fetch<'w> = &'w World; | ||
type Item<'w> = EntityRef<'w>; | ||
type ReadOnly = Self; | ||
type State = (); | ||
|
||
fn shrink<'wlong: 'wshort, 'wshort>(item: Self::Item<'wlong>) -> Self::Item<'wshort> { | ||
item | ||
} | ||
|
||
const IS_DENSE: bool = true; | ||
|
||
const IS_ARCHETYPAL: bool = true; | ||
|
||
unsafe fn init_fetch<'w>( | ||
world: UnsafeWorldCell<'w>, | ||
_state: &Self::State, | ||
_last_run: Tick, | ||
_this_run: Tick, | ||
) -> Self::Fetch<'w> { | ||
// SAFE: EntityRef has permission to access the whole world immutably thanks to update_component_access and update_archetype_component_access | ||
world.world() | ||
} | ||
|
||
unsafe fn clone_fetch<'w>(world: &Self::Fetch<'w>) -> Self::Fetch<'w> { | ||
world | ||
} | ||
|
||
#[inline] | ||
unsafe fn set_archetype<'w>( | ||
_fetch: &mut Self::Fetch<'w>, | ||
_state: &Self::State, | ||
_archetype: &'w Archetype, | ||
_table: &Table, | ||
) { | ||
} | ||
|
||
#[inline] | ||
unsafe fn set_table<'w>(_fetch: &mut Self::Fetch<'w>, _state: &Self::State, _table: &'w Table) { | ||
} | ||
|
||
#[inline(always)] | ||
unsafe fn fetch<'w>( | ||
world: &mut Self::Fetch<'w>, | ||
entity: Entity, | ||
_table_row: TableRow, | ||
) -> Self::Item<'w> { | ||
// SAFETY: `fetch` must be called with an entity that exists in the world | ||
unsafe { world.get_entity(entity).debug_checked_unwrap() } | ||
} | ||
|
||
fn update_component_access(_state: &Self::State, access: &mut FilteredAccess<ComponentId>) { | ||
assert!( | ||
!access.access().has_any_write(), | ||
"EntityRef conflicts with a previous access in this query. Shared access cannot coincide with exclusive access.", | ||
); | ||
access.read_all(); | ||
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. Does a 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. No, but a 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'd prefer to split that out (and I do think that should be done): that sort of work needs careful review. 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. Should I address this as a part of this PR or should I leave this for later? 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. Leave it until later please. |
||
} | ||
|
||
fn update_archetype_component_access( | ||
_state: &Self::State, | ||
archetype: &Archetype, | ||
access: &mut Access<ArchetypeComponentId>, | ||
) { | ||
for component_id in archetype.components() { | ||
access.add_read(archetype.get_archetype_component_id(component_id).unwrap()); | ||
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. This means that you can have a system with 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. That's probably still fine since it only mutates the command queue and not the entity directly. 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. Yeah I didn't expect it to be unsound, just something to keep in mind where a system may panic depending on the entities and components in the world. Like how |
||
} | ||
} | ||
|
||
fn init_state(_world: &mut World) {} | ||
|
||
fn matches_component_set( | ||
_state: &Self::State, | ||
_set_contains_id: &impl Fn(ComponentId) -> bool, | ||
) -> bool { | ||
true | ||
} | ||
} | ||
|
||
/// SAFETY: access is read only | ||
unsafe impl<'a> ReadOnlyWorldQuery for EntityRef<'a> {} | ||
|
||
#[doc(hidden)] | ||
pub struct ReadFetch<'w, T> { | ||
// T::Storage = TableStorage | ||
|
Uh oh!
There was an error while loading. Please reload this page.