bevy_trait_query/one/impls/
with_one.rs

1use std::marker::PhantomData;
2
3use bevy_ecs::{
4    component::{ComponentId, Components, Tick},
5    prelude::{Entity, World},
6    query::{ArchetypeFilter, QueryFilter, WorldQuery},
7    storage::TableRow,
8    world::unsafe_world_cell::UnsafeWorldCell,
9};
10
11use crate::{TraitQuery, TraitQueryState};
12
13/// [`WorldQuery`] filter for entities with exactly [one](crate::One) component
14/// implementing a trait.
15pub struct WithOne<Trait: ?Sized + TraitQuery>(PhantomData<&'static Trait>);
16
17// this takes inspiration from `With` in bevy's main repo
18unsafe impl<Trait: ?Sized + TraitQuery> WorldQuery for WithOne<Trait> {
19    type Fetch<'w> = ();
20    type State = TraitQueryState<Trait>;
21
22    #[inline]
23    unsafe fn init_fetch(
24        _world: UnsafeWorldCell<'_>,
25        _state: &Self::State,
26        _last_run: Tick,
27        _this_run: Tick,
28    ) {
29    }
30
31    const IS_DENSE: bool = false;
32
33    #[inline]
34    unsafe fn set_archetype<'w>(
35        _fetch: &mut (),
36        _state: &Self::State,
37        _archetype: &'w bevy_ecs::archetype::Archetype,
38        _table: &'w bevy_ecs::storage::Table,
39    ) {
40    }
41
42    #[inline]
43    unsafe fn set_table(_fetch: &mut (), _state: &Self::State, _table: &bevy_ecs::storage::Table) {}
44
45    #[inline]
46    fn update_component_access(state: &Self::State, access: &mut bevy_ecs::query::FilteredAccess) {
47        let mut new_access = access.clone();
48        for &component in state.components.iter() {
49            let mut intermediate = access.clone();
50            intermediate.and_with(component);
51            new_access.append_or(&intermediate);
52        }
53        *access = new_access;
54    }
55
56    #[inline]
57    fn init_state(world: &mut World) -> Self::State {
58        TraitQueryState::init(world)
59    }
60
61    #[inline]
62    fn get_state(_: &Components) -> Option<Self::State> {
63        // TODO: fix this https://github.com/bevyengine/bevy/issues/13798
64        panic!(
65            "transmuting and any other operations concerning the state of a query are currently broken and shouldn't be used. See https://github.com/JoJoJet/bevy-trait-query/issues/59"
66        );
67    }
68
69    #[inline]
70    fn matches_component_set(
71        state: &Self::State,
72        set_contains_id: &impl Fn(ComponentId) -> bool,
73    ) -> bool {
74        state.matches_component_set_one(set_contains_id)
75    }
76
77    #[inline]
78    fn shrink_fetch<'wlong: 'wshort, 'wshort>(_fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {
79    }
80}
81
82impl<Trait: ?Sized + TraitQuery> ArchetypeFilter for WithOne<Trait> {}
83
84/// SAFETY: read-only access
85unsafe impl<Trait: ?Sized + TraitQuery> QueryFilter for WithOne<Trait> {
86    const IS_ARCHETYPAL: bool = false;
87    unsafe fn filter_fetch(
88        _state: &Self::State,
89        _fetch: &mut Self::Fetch<'_>,
90        _entity: Entity,
91        _table_row: TableRow,
92    ) -> bool {
93        true
94    }
95}