Skip to content

Commit c57f013

Browse files
RobWaltAzorloghjoseph-gio
authored
Bevy 0.13 Update PR (#55)
* chore(update): bump crate versions and adjust README Authored-by: RobWalt <[email protected]> * chore(update): update in main crate - change `ReadOnlyWoldQuery` to `ReadOnlyQueryData` - additionally implement `QueryData` - change the impls for `WorldQuery` - add a new method on the `TraitQueryState` to get it from the world Authored-by: RobWalt <[email protected]> * chore(cleanup): remove unused tests Authored-by: Robert Walter <[email protected]> * chore(update): get it to compile again, tests fail - tests fail completely Authored-by: RobWalt <[email protected]> * fix update_component_access, remove QueryFilter for All, remove ReadOnlyQueryData for One<&'a mut T> * warning * fix remaining uses of update_component_access * chore(update): add `ReadOnly` for `All<&'a mut Trait>` Authored-by: RobWalt <[email protected]> * chore(cleanup): remove leftover commented out code Authored-by: RobWalt <[email protected]> * chore(cleanup): further fixes Authored-by: RobWalt <[email protected]> Reviewed-by: Azorlogh <[email protected]> * fixup! chore(cleanup): further fixes * chore(update): implement review suggestion to fix `_required` field issues Authored-by: RobWalt <[email protected]> Reviewed-by: SkiFire13 * chore(fix): update proc macro for `QueryData` to include lifetimes Authored-by: RobWalt <[email protected]> * chore(update): make `ReadOnly` of `&mut trait` really read only Authored-by: RobWalt <[email protected]> Reviewed-by: Azorlogh <[email protected]> * feat(one): add `QueryFilter` struct `WithOne` Authored-by: RobWalt <[email protected]> * make clippy happy 💖 * cargo fmt --------- Co-authored-by: Azorlogh <[email protected]> Co-authored-by: Joseph <[email protected]>
1 parent 2869f9d commit c57f013

File tree

7 files changed

+352
-160
lines changed

7 files changed

+352
-160
lines changed

Cargo.toml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "bevy-trait-query"
3-
version = "0.4.0"
3+
version = "0.5.0"
44
edition = "2021"
55

66
description = "Implementation of trait queries for the bevy game engine"
@@ -19,21 +19,21 @@ bevy-trait-query-impl = { path = "proc-macro", version = "0.4.0" }
1919
tracing = "0.1"
2020

2121
[dependencies.bevy_ecs]
22-
version = "0.12"
22+
version = "0.13"
2323

2424
[dependencies.bevy_app]
25-
version = "0.12"
25+
version = "0.13"
2626
optional = true
2727

2828
[dependencies.bevy_core]
29-
version = "0.12"
29+
version = "0.13"
3030
optional = true
3131

3232
[dev-dependencies]
3333
criterion = "0.5"
3434

3535
[dev-dependencies.bevy]
36-
version = "0.12"
36+
version = "0.13"
3737
default-features = false
3838

3939
[[bench]]

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ Before using this crate, you should be familiar with bevy: https://bevyengine.or
66

77
| Bevy Version | [Crate Version](CHANGELOG.md) |
88
|--------------|---------------|
9+
| 0.13 | 0.5 |
910
| 0.12 | 0.4 |
1011
| 0.11 | 0.3 |
1112
| 0.10 | 0.2 |

proc-macro/src/lib.rs

Lines changed: 20 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,12 @@ fn impl_trait_query(arg: TokenStream, item: TokenStream) -> Result<TokenStream2>
148148
let impl_generics_with_lifetime = quote! { <#( #impl_generics_with_lifetime ,)*> };
149149

150150
let trait_object_query_code = quote! {
151-
unsafe impl #impl_generics #imports::ReadOnlyWorldQuery for &#trait_object
151+
unsafe impl #impl_generics #imports::QueryData for &#trait_object
152+
#where_clause
153+
{
154+
type ReadOnly = Self;
155+
}
156+
unsafe impl #impl_generics #imports::ReadOnlyQueryData for &#trait_object
152157
#where_clause
153158
{}
154159

@@ -157,7 +162,6 @@ fn impl_trait_query(arg: TokenStream, item: TokenStream) -> Result<TokenStream2>
157162
{
158163
type Item<'__w> = #my_crate::ReadTraits<'__w, #trait_object>;
159164
type Fetch<'__w> = <#my_crate::All<&'__a #trait_object> as #imports::WorldQuery>::Fetch<'__w>;
160-
type ReadOnly = Self;
161165
type State = #my_crate::TraitQueryState<#trait_object>;
162166

163167
#[inline]
@@ -183,8 +187,6 @@ fn impl_trait_query(arg: TokenStream, item: TokenStream) -> Result<TokenStream2>
183187
}
184188

185189
const IS_DENSE: bool = <#my_crate::All<&#trait_object> as #imports::WorldQuery>::IS_DENSE;
186-
const IS_ARCHETYPAL: bool =
187-
<#my_crate::All<&#trait_object> as #imports::WorldQuery>::IS_ARCHETYPAL;
188190

189191
#[inline]
190192
unsafe fn set_archetype<'w>(
@@ -231,17 +233,13 @@ fn impl_trait_query(arg: TokenStream, item: TokenStream) -> Result<TokenStream2>
231233
}
232234

233235
#[inline]
234-
fn update_archetype_component_access(
235-
state: &Self::State,
236-
archetype: &#imports::Archetype,
237-
access: &mut #imports::Access<#imports::ArchetypeComponentId>,
238-
) {
239-
<#my_crate::All<&#trait_object> as #imports::WorldQuery>::update_archetype_component_access(state, archetype, access);
236+
fn init_state(world: &mut #imports::World) -> Self::State {
237+
<#my_crate::All<&#trait_object> as #imports::WorldQuery>::init_state(world)
240238
}
241239

242240
#[inline]
243-
fn init_state(world: &mut #imports::World) -> Self::State {
244-
<#my_crate::All<&#trait_object> as #imports::WorldQuery>::init_state(world)
241+
fn get_state(world: &#imports::World) -> Option<Self::State> {
242+
<#my_crate::All<&#trait_object> as #imports::WorldQuery>::get_state(world)
245243
}
246244

247245
#[inline]
@@ -253,12 +251,17 @@ fn impl_trait_query(arg: TokenStream, item: TokenStream) -> Result<TokenStream2>
253251
}
254252
}
255253

254+
unsafe impl #impl_generics_with_lifetime #imports::QueryData for &'__a mut #trait_object
255+
#where_clause
256+
{
257+
type ReadOnly = &'__a #trait_object;
258+
}
259+
256260
unsafe impl #impl_generics_with_lifetime #imports::WorldQuery for &'__a mut #trait_object
257261
#where_clause
258262
{
259263
type Item<'__w> = #my_crate::WriteTraits<'__w, #trait_object>;
260264
type Fetch<'__w> = <#my_crate::All<&'__a #trait_object> as #imports::WorldQuery>::Fetch<'__w>;
261-
type ReadOnly = &'__a #trait_object;
262265
type State = #my_crate::TraitQueryState<#trait_object>;
263266

264267
#[inline]
@@ -284,8 +287,6 @@ fn impl_trait_query(arg: TokenStream, item: TokenStream) -> Result<TokenStream2>
284287
}
285288

286289
const IS_DENSE: bool = <#my_crate::All<&mut #trait_object> as #imports::WorldQuery>::IS_DENSE;
287-
const IS_ARCHETYPAL: bool =
288-
<#my_crate::All<&mut #trait_object> as #imports::WorldQuery>::IS_ARCHETYPAL;
289290

290291
#[inline]
291292
unsafe fn set_archetype<'w>(
@@ -332,18 +333,13 @@ fn impl_trait_query(arg: TokenStream, item: TokenStream) -> Result<TokenStream2>
332333
}
333334

334335
#[inline]
335-
fn update_archetype_component_access(
336-
state: &Self::State,
337-
archetype: &#imports::Archetype,
338-
access: &mut #imports::Access<#imports::ArchetypeComponentId>,
339-
) {
340-
<#my_crate::All<&mut #trait_object> as #imports::WorldQuery>::update_archetype_component_access(state, archetype, access);
336+
fn init_state(world: &mut #imports::World) -> Self::State {
337+
<#my_crate::All<&mut #trait_object> as #imports::WorldQuery>::init_state(world)
341338
}
342339

343-
344340
#[inline]
345-
fn init_state(world: &mut #imports::World) -> Self::State {
346-
<#my_crate::All<&mut #trait_object> as #imports::WorldQuery>::init_state(world)
341+
fn get_state(world: &#imports::World) -> Option<Self::State> {
342+
<#my_crate::All<&mut #trait_object> as #imports::WorldQuery>::get_state(world)
347343
}
348344

349345
#[inline]
@@ -364,14 +360,3 @@ fn impl_trait_query(arg: TokenStream, item: TokenStream) -> Result<TokenStream2>
364360
#trait_object_query_code
365361
})
366362
}
367-
368-
#[cfg(test)]
369-
mod tests {
370-
use super::*;
371-
372-
#[test]
373-
fn it_works() {
374-
let result = add(2, 2);
375-
assert_eq!(result, 4);
376-
}
377-
}

src/all.rs

Lines changed: 52 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use bevy_ecs::{
33
component::{ComponentId, Tick},
44
entity::Entity,
55
ptr::UnsafeCellDeref,
6-
query::{QueryItem, ReadOnlyWorldQuery, WorldQuery},
6+
query::{QueryData, QueryItem, ReadOnlyQueryData, WorldQuery},
77
storage::{SparseSets, Table, TableRow},
88
world::{unsafe_world_cell::UnsafeWorldCell, World},
99
};
@@ -58,7 +58,7 @@ impl<'a, Trait: ?Sized + TraitQuery> Iterator for ReadTableTraitsIter<'a, Trait>
5858
let ptr = unsafe {
5959
column
6060
.get_data_ptr()
61-
.byte_add(self.table_row.index() * meta.size_bytes)
61+
.byte_add(self.table_row.as_usize() * meta.size_bytes)
6262
};
6363
let trait_object = unsafe { meta.dyn_ctor.cast(ptr) };
6464

@@ -130,7 +130,7 @@ impl<'w, Trait: ?Sized + TraitQuery> IntoIterator for ReadTraits<'w, Trait> {
130130
let sparse = ReadSparseTraitsIter {
131131
components: self.registry.sparse_components.iter(),
132132
meta: self.registry.sparse_meta.iter(),
133-
entity: self.table.entities()[self.table_row.index()],
133+
entity: self.table.entities()[self.table_row.as_usize()],
134134
sparse_sets: self.sparse_sets,
135135
last_run: self.last_run,
136136
this_run: self.this_run,
@@ -155,7 +155,7 @@ impl<'w, Trait: ?Sized + TraitQuery> IntoIterator for &ReadTraits<'w, Trait> {
155155
let sparse = ReadSparseTraitsIter {
156156
components: self.registry.sparse_components.iter(),
157157
meta: self.registry.sparse_meta.iter(),
158-
entity: self.table.entities()[self.table_row.index()],
158+
entity: self.table.entities()[self.table_row.as_usize()],
159159
sparse_sets: self.sparse_sets,
160160
last_run: self.last_run,
161161
this_run: self.this_run,
@@ -246,7 +246,7 @@ impl<'a, Trait: ?Sized + TraitQuery> Iterator for WriteTableTraitsIter<'a, Trait
246246
let ptr = unsafe {
247247
column
248248
.get_data_ptr()
249-
.byte_add(self.table_row.index() * meta.size_bytes)
249+
.byte_add(self.table_row.as_usize() * meta.size_bytes)
250250
};
251251
// SAFETY: The instance of `WriteTraits` that created this iterator
252252
// has exclusive access to all table components registered with the trait.
@@ -375,7 +375,7 @@ impl<'w, Trait: ?Sized + TraitQuery> IntoIterator for WriteTraits<'w, Trait> {
375375
let sparse = WriteSparseTraitsIter {
376376
components: self.registry.sparse_components.iter(),
377377
meta: self.registry.sparse_meta.iter(),
378-
entity: self.table.entities()[self.table_row.index()],
378+
entity: self.table.entities()[self.table_row.as_usize()],
379379
sparse_sets: self.sparse_sets,
380380
last_run: self.last_run,
381381
this_run: self.this_run,
@@ -402,7 +402,7 @@ impl<'world, 'local, Trait: ?Sized + TraitQuery> IntoIterator
402402
let sparse = ReadSparseTraitsIter {
403403
components: self.registry.sparse_components.iter(),
404404
meta: self.registry.sparse_meta.iter(),
405-
entity: self.table.entities()[self.table_row.index()],
405+
entity: self.table.entities()[self.table_row.as_usize()],
406406
sparse_sets: self.sparse_sets,
407407
last_run: self.last_run,
408408
this_run: self.this_run,
@@ -429,7 +429,7 @@ impl<'world, 'local, Trait: ?Sized + TraitQuery> IntoIterator
429429
let sparse = WriteSparseTraitsIter {
430430
components: self.registry.sparse_components.iter(),
431431
meta: self.registry.sparse_meta.iter(),
432-
entity: self.table.entities()[self.table_row.index()],
432+
entity: self.table.entities()[self.table_row.as_usize()],
433433
sparse_sets: self.sparse_sets,
434434
last_run: self.last_run,
435435
this_run: self.this_run,
@@ -443,15 +443,17 @@ impl<'world, 'local, Trait: ?Sized + TraitQuery> IntoIterator
443443
/// You can usually just use `&dyn Trait` or `&mut dyn Trait` as a `WorldQuery` directly.
444444
pub struct All<T: ?Sized>(T);
445445

446-
unsafe impl<'a, Trait: ?Sized + TraitQuery> ReadOnlyWorldQuery for All<&'a Trait> {}
446+
unsafe impl<'a, Trait: ?Sized + TraitQuery> QueryData for All<&'a Trait> {
447+
type ReadOnly = Self;
448+
}
449+
unsafe impl<'a, Trait: ?Sized + TraitQuery> ReadOnlyQueryData for All<&'a Trait> {}
447450

448451
// SAFETY: We only access the components registered in the trait registry.
449452
// This is known to match the set of components in the TraitQueryState,
450453
// which is used to match archetypes and register world access.
451454
unsafe impl<'a, Trait: ?Sized + TraitQuery> WorldQuery for All<&'a Trait> {
452455
type Item<'w> = ReadTraits<'w, Trait>;
453456
type Fetch<'w> = AllTraitsFetch<'w, Trait>;
454-
type ReadOnly = Self;
455457
type State = TraitQueryState<Trait>;
456458

457459
#[inline]
@@ -478,7 +480,6 @@ unsafe impl<'a, Trait: ?Sized + TraitQuery> WorldQuery for All<&'a Trait> {
478480
}
479481

480482
const IS_DENSE: bool = false;
481-
const IS_ARCHETYPAL: bool = false;
482483

483484
#[inline]
484485
unsafe fn set_archetype<'w>(
@@ -521,33 +522,38 @@ unsafe impl<'a, Trait: ?Sized + TraitQuery> WorldQuery for All<&'a Trait> {
521522
state: &Self::State,
522523
access: &mut bevy_ecs::query::FilteredAccess<ComponentId>,
523524
) {
525+
let mut not_first = false;
526+
let mut new_access = access.clone();
524527
for &component in &*state.components {
525528
assert!(
526529
!access.access().has_write(component),
527530
"&{} conflicts with a previous access in this query. Shared access cannot coincide with exclusive access.",
528531
std::any::type_name::<Trait>(),
529532
);
530-
access.add_read(component);
531-
}
532-
}
533-
534-
#[inline]
535-
fn update_archetype_component_access(
536-
state: &Self::State,
537-
archetype: &bevy_ecs::archetype::Archetype,
538-
access: &mut bevy_ecs::query::Access<bevy_ecs::archetype::ArchetypeComponentId>,
539-
) {
540-
for &component in &*state.components {
541-
if let Some(archetype_component_id) = archetype.get_archetype_component_id(component) {
542-
access.add_read(archetype_component_id);
533+
if not_first {
534+
let mut intermediate = access.clone();
535+
intermediate.add_read(component);
536+
new_access.append_or(&intermediate);
537+
new_access.extend_access(&intermediate);
538+
} else {
539+
new_access.and_with(component);
540+
new_access.access_mut().add_read(component);
541+
not_first = true;
543542
}
544543
}
544+
*access = new_access;
545545
}
546546

547547
#[inline]
548548
fn init_state(world: &mut World) -> Self::State {
549549
TraitQueryState::init(world)
550550
}
551+
552+
#[inline]
553+
fn get_state(world: &World) -> Option<Self::State> {
554+
TraitQueryState::get(world)
555+
}
556+
551557
#[inline]
552558
fn matches_component_set(
553559
state: &Self::State,
@@ -557,13 +563,16 @@ unsafe impl<'a, Trait: ?Sized + TraitQuery> WorldQuery for All<&'a Trait> {
557563
}
558564
}
559565

566+
unsafe impl<'a, Trait: ?Sized + TraitQuery> QueryData for All<&'a mut Trait> {
567+
type ReadOnly = All<&'a Trait>;
568+
}
569+
560570
// SAFETY: We only access the components registered in the trait registry.
561571
// This is known to match the set of components in the TraitQueryState,
562572
// which is used to match archetypes and register world access.
563573
unsafe impl<'a, Trait: ?Sized + TraitQuery> WorldQuery for All<&'a mut Trait> {
564574
type Item<'w> = WriteTraits<'w, Trait>;
565575
type Fetch<'w> = AllTraitsFetch<'w, Trait>;
566-
type ReadOnly = All<&'a Trait>;
567576
type State = TraitQueryState<Trait>;
568577

569578
#[inline]
@@ -590,7 +599,6 @@ unsafe impl<'a, Trait: ?Sized + TraitQuery> WorldQuery for All<&'a mut Trait> {
590599
}
591600

592601
const IS_DENSE: bool = false;
593-
const IS_ARCHETYPAL: bool = false;
594602

595603
#[inline]
596604
unsafe fn set_archetype<'w>(
@@ -634,33 +642,38 @@ unsafe impl<'a, Trait: ?Sized + TraitQuery> WorldQuery for All<&'a mut Trait> {
634642
state: &Self::State,
635643
access: &mut bevy_ecs::query::FilteredAccess<ComponentId>,
636644
) {
645+
let mut not_first = false;
646+
let mut new_access = access.clone();
637647
for &component in &*state.components {
638648
assert!(
639649
!access.access().has_write(component),
640650
"&mut {} conflicts with a previous access in this query. Mutable component access must be unique.",
641651
std::any::type_name::<Trait>(),
642652
);
643-
access.add_write(component);
644-
}
645-
}
646-
647-
#[inline]
648-
fn update_archetype_component_access(
649-
state: &Self::State,
650-
archetype: &bevy_ecs::archetype::Archetype,
651-
access: &mut bevy_ecs::query::Access<bevy_ecs::archetype::ArchetypeComponentId>,
652-
) {
653-
for &component in &*state.components {
654-
if let Some(archetype_component_id) = archetype.get_archetype_component_id(component) {
655-
access.add_write(archetype_component_id);
653+
if not_first {
654+
let mut intermediate = access.clone();
655+
intermediate.add_write(component);
656+
new_access.append_or(&intermediate);
657+
new_access.extend_access(&intermediate);
658+
} else {
659+
new_access.and_with(component);
660+
new_access.access_mut().add_write(component);
661+
not_first = true;
656662
}
657663
}
664+
*access = new_access;
658665
}
659666

660667
#[inline]
661668
fn init_state(world: &mut World) -> Self::State {
662669
TraitQueryState::init(world)
663670
}
671+
672+
#[inline]
673+
fn get_state(world: &World) -> Option<Self::State> {
674+
TraitQueryState::get(world)
675+
}
676+
664677
#[inline]
665678
fn matches_component_set(
666679
state: &Self::State,

0 commit comments

Comments
 (0)