Skip to content

Commit

Permalink
do it
Browse files Browse the repository at this point in the history
  • Loading branch information
BoxyUwU committed Aug 6, 2022
1 parent c27cc59 commit 750d894
Show file tree
Hide file tree
Showing 5 changed files with 161 additions and 116 deletions.
14 changes: 13 additions & 1 deletion crates/bevy_ecs/macros/src/fetch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,6 @@ pub fn derive_world_query_impl(ast: DeriveInput) -> TokenStream {
#(#(#ignored_field_attrs)* #ignored_field_visibilities #ignored_field_idents: #ignored_field_types,)*
}

#[derive(Clone)]
#[doc(hidden)]
#visibility struct #fetch_struct_name #user_impl_generics_with_world #user_where_clauses_with_world {
#(#field_idents: <#field_types as #path::query::WorldQueryGats<'__w>>::Fetch,)*
Expand Down Expand Up @@ -239,6 +238,19 @@ pub fn derive_world_query_impl(ast: DeriveInput) -> TokenStream {
}
}

unsafe fn clone_fetch<'__w>(
_fetch: &<Self as #path::query::WorldQueryGats<'__w>>::Fetch
) -> <Self as #path::query::WorldQueryGats<'__w>>::Fetch {
#fetch_struct_name {
#(
#field_idents: <#field_types>::clone_fetch(& _fetch. #field_idents),
)*
#(
#ignored_field_idents: Default::default(),
)*
}
}

const IS_DENSE: bool = true #(&& <#field_types>::IS_DENSE)*;

const IS_ARCHETYPAL: bool = true #(&& <#field_types>::IS_ARCHETYPAL)*;
Expand Down
150 changes: 97 additions & 53 deletions crates/bevy_ecs/src/query/fetch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,16 @@ pub unsafe trait WorldQuery: for<'w> WorldQueryGats<'w> {
change_tick: u32,
) -> <Self as WorldQueryGats<'w>>::Fetch;

/// This function is safe to call if `Self:ReadOnlyWorldQuery` holds.
///
/// # Safety
/// While calling this method on its own cannot cause UB it is marked `unsafe` as the caller must ensure
/// that the returned value is not used in any way that would cause two `QueryItem<Self>` for the same
/// `archetype_index` or `table_row` to be alive at the same time.
unsafe fn clone_fetch<'w>(
fetch: &<Self as WorldQueryGats<'w>>::Fetch,
) -> <Self as WorldQueryGats<'w>>::Fetch;

/// Returns true if (and only if) every table of every archetype matched by this fetch contains
/// all of the matched components. This is used to select a more efficient "table iterator"
/// for "dense" queries. If this returns true, [`WorldQuery::set_table`] and [`WorldQuery::table_fetch`]
Expand Down Expand Up @@ -482,7 +492,6 @@ pub type ROQueryFetch<'w, Q> = QueryFetch<'w, <Q as WorldQuery>::ReadOnly>;
pub type ROQueryItem<'w, Q> = QueryItem<'w, <Q as WorldQuery>::ReadOnly>;

#[doc(hidden)]
#[derive(Clone)]
pub struct EntityFetch<'w> {
entities: Option<ThinSlicePtr<'w, Entity>>,
}
Expand All @@ -509,6 +518,14 @@ unsafe impl WorldQuery for Entity {
EntityFetch { entities: None }
}

unsafe fn clone_fetch<'w>(
fetch: &<Self as WorldQueryGats<'w>>::Fetch,
) -> <Self as WorldQueryGats<'w>>::Fetch {
EntityFetch {
entities: fetch.entities,
}
}

#[inline]
unsafe fn set_archetype<'w>(
fetch: &mut EntityFetch<'w>,
Expand Down Expand Up @@ -616,6 +633,17 @@ unsafe impl<T: Component> WorldQuery for &T {
}
}

unsafe fn clone_fetch<'w>(
fetch: &<Self as WorldQueryGats<'w>>::Fetch,
) -> <Self as WorldQueryGats<'w>>::Fetch {
ReadFetch {
table_components: fetch.table_components,
entity_table_rows: fetch.entity_table_rows,
entities: fetch.entities,
sparse_set: fetch.sparse_set,
}
}

#[inline]
unsafe fn set_archetype<'w>(
fetch: &mut ReadFetch<'w, T>,
Expand Down Expand Up @@ -713,17 +741,6 @@ unsafe impl<T: Component> WorldQuery for &T {
}
}

impl<T> Clone for ReadFetch<'_, T> {
fn clone(&self) -> Self {
Self {
table_components: self.table_components,
entity_table_rows: self.entity_table_rows,
entities: self.entities,
sparse_set: self.sparse_set,
}
}
}

/// SAFETY: access is read only
unsafe impl<T: Component> ReadOnlyWorldQuery for &T {}

Expand Down Expand Up @@ -782,6 +799,20 @@ unsafe impl<'__w, T: Component> WorldQuery for &'__w mut T {
}
}

unsafe fn clone_fetch<'w>(
fetch: &<Self as WorldQueryGats<'w>>::Fetch,
) -> <Self as WorldQueryGats<'w>>::Fetch {
WriteFetch {
table_components: fetch.table_components,
table_ticks: fetch.table_ticks,
entities: fetch.entities,
entity_table_rows: fetch.entity_table_rows,
sparse_set: fetch.sparse_set,
last_change_tick: fetch.last_change_tick,
change_tick: fetch.change_tick,
}
}

#[inline]
unsafe fn set_archetype<'w>(
fetch: &mut WriteFetch<'w, T>,
Expand Down Expand Up @@ -908,20 +939,6 @@ unsafe impl<'__w, T: Component> WorldQuery for &'__w mut T {
}
}

impl<T> Clone for WriteFetch<'_, T> {
fn clone(&self) -> Self {
Self {
table_components: self.table_components,
table_ticks: self.table_ticks,
entities: self.entities,
entity_table_rows: self.entity_table_rows,
sparse_set: self.sparse_set,
last_change_tick: self.last_change_tick,
change_tick: self.change_tick,
}
}
}

impl<'w, T: Component> WorldQueryGats<'w> for &mut T {
type Fetch = WriteFetch<'w, T>;
type Item = Mut<'w, T>;
Expand All @@ -932,17 +949,6 @@ pub struct OptionFetch<'w, T: WorldQuery> {
fetch: <T as WorldQueryGats<'w>>::Fetch,
matches: bool,
}
impl<'w, T: WorldQuery> Clone for OptionFetch<'w, T>
where
<T as WorldQueryGats<'w>>::Fetch: Clone,
{
fn clone(&self) -> Self {
Self {
fetch: self.fetch.clone(),
matches: self.matches,
}
}
}

// SAFETY: defers to soundness of `T: WorldQuery` impl
unsafe impl<T: WorldQuery> WorldQuery for Option<T> {
Expand All @@ -969,6 +975,15 @@ unsafe impl<T: WorldQuery> WorldQuery for Option<T> {
}
}

unsafe fn clone_fetch<'w>(
fetch: &<Self as WorldQueryGats<'w>>::Fetch,
) -> <Self as WorldQueryGats<'w>>::Fetch {
OptionFetch {
fetch: T::clone_fetch(&fetch.fetch),
matches: fetch.matches,
}
}

#[inline]
unsafe fn set_archetype<'w>(
fetch: &mut OptionFetch<'w, T>,
Expand Down Expand Up @@ -1086,14 +1101,25 @@ impl<'w, T: WorldQuery> WorldQueryGats<'w> for Option<T> {
/// }
/// # bevy_ecs::system::assert_is_system(print_moving_objects_system);
/// ```
#[derive(Clone)]
pub struct ChangeTrackers<T: Component> {
pub(crate) component_ticks: ComponentTicks,
pub(crate) last_change_tick: u32,
pub(crate) change_tick: u32,
marker: PhantomData<T>,
}

impl<T: Component> Clone for ChangeTrackers<T> {
fn clone(&self) -> Self {
Self {
component_ticks: self.component_ticks,
last_change_tick: self.last_change_tick,
change_tick: self.change_tick,
marker: PhantomData,
}
}
}
impl<T: Component> Copy for ChangeTrackers<T> {}

impl<T: Component> std::fmt::Debug for ChangeTrackers<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ChangeTrackers")
Expand Down Expand Up @@ -1132,20 +1158,6 @@ pub struct ChangeTrackersFetch<'w, T> {
change_tick: u32,
}

impl<T> Clone for ChangeTrackersFetch<'_, T> {
fn clone(&self) -> Self {
Self {
table_ticks: self.table_ticks,
entity_table_rows: self.entity_table_rows,
entities: self.entities,
sparse_set: self.sparse_set,
marker: self.marker,
last_change_tick: self.last_change_tick,
change_tick: self.change_tick,
}
}
}

// SAFETY: `ROQueryFetch<Self>` is the same as `QueryFetch<Self>`
unsafe impl<T: Component> WorldQuery for ChangeTrackers<T> {
type ReadOnly = Self;
Expand Down Expand Up @@ -1182,6 +1194,20 @@ unsafe impl<T: Component> WorldQuery for ChangeTrackers<T> {
}
}

unsafe fn clone_fetch<'w>(
fetch: &<Self as WorldQueryGats<'w>>::Fetch,
) -> <Self as WorldQueryGats<'w>>::Fetch {
ChangeTrackersFetch {
table_ticks: fetch.table_ticks,
entity_table_rows: fetch.entity_table_rows,
entities: fetch.entities,
sparse_set: fetch.sparse_set,
marker: fetch.marker,
last_change_tick: fetch.last_change_tick,
change_tick: fetch.change_tick,
}
}

#[inline]
unsafe fn set_archetype<'w>(
fetch: &mut ChangeTrackersFetch<'w, T>,
Expand Down Expand Up @@ -1338,6 +1364,13 @@ macro_rules! impl_tuple_fetch {
($($name::init_fetch(_world, $name, _last_change_tick, _change_tick),)*)
}

unsafe fn clone_fetch<'w>(
fetch: &<Self as WorldQueryGats<'w>>::Fetch,
) -> <Self as WorldQueryGats<'w>>::Fetch {
let ($($name,)*) = &fetch;
($($name::clone_fetch($name),)*)
}

const IS_DENSE: bool = true $(&& $name::IS_DENSE)*;

const IS_ARCHETYPAL: bool = true $(&& $name::IS_ARCHETYPAL)*;
Expand Down Expand Up @@ -1416,7 +1449,6 @@ macro_rules! impl_tuple_fetch {
/// `Query<AnyOf<(&A, &B, &mut C)>>` is equivalent to `Query<(Option<&A>, Option<&B>, Option<&mut C>), (Or(With<A>, With<B>, With<C>)>`.
/// Each of the components in `T` is returned as an `Option`, as with `Option<A>` queries.
/// Entities are guaranteed to have at least one of the components in `T`.
#[derive(Clone)]
pub struct AnyOf<T>(PhantomData<T>);

macro_rules! impl_anytuple_fetch {
Expand Down Expand Up @@ -1448,6 +1480,13 @@ macro_rules! impl_anytuple_fetch {
($(($name::init_fetch(_world, $name, _last_change_tick, _change_tick), false),)*)
}

unsafe fn clone_fetch<'w>(
fetch: &<Self as WorldQueryGats<'w>>::Fetch,
) -> <Self as WorldQueryGats<'w>>::Fetch {
let ($($name,)*) = &fetch;
($(($name::clone_fetch(& $name.0), $name.1),)*)
}

const IS_DENSE: bool = true $(&& $name::IS_DENSE)*;

const IS_ARCHETYPAL: bool = true $(&& $name::IS_ARCHETYPAL)*;
Expand Down Expand Up @@ -1580,6 +1619,11 @@ unsafe impl<Q: WorldQuery> WorldQuery for NopWorldQuery<Q> {
) {
}

unsafe fn clone_fetch<'w>(
_fetch: &<Self as WorldQueryGats<'w>>::Fetch,
) -> <Self as WorldQueryGats<'w>>::Fetch {
}

#[inline(always)]
unsafe fn set_archetype(
_fetch: &mut (),
Expand Down
Loading

0 comments on commit 750d894

Please sign in to comment.