bevy_trait_query/all/impls/
all.rs1use bevy_ecs::{
2 component::{ComponentId, Components, Tick},
3 entity::Entity,
4 query::{QueryData, QueryItem, ReadOnlyQueryData, WorldQuery},
5 storage::TableRow,
6 world::{World, unsafe_world_cell::UnsafeWorldCell},
7};
8
9use crate::{
10 AllTraitsFetch, ReadTraits, TraitQuery, TraitQueryState, WriteTraits, debug_unreachable,
11 trait_registry_error,
12};
13
14pub struct All<T: ?Sized>(T);
28
29unsafe impl<Trait: ?Sized + TraitQuery> QueryData for All<&Trait> {
30 type ReadOnly = Self;
31
32 const IS_READ_ONLY: bool = true;
33
34 type Item<'w, 's> = ReadTraits<'w, Trait>;
35
36 #[inline]
37 fn shrink<'wlong: 'wshort, 'wshort, 's>(
38 item: QueryItem<'wlong, 's, Self>,
39 ) -> QueryItem<'wshort, 's, Self> {
40 item
41 }
42
43 #[inline]
44 unsafe fn fetch<'w, 's>(
45 _state: &'s Self::State,
46 fetch: &mut Self::Fetch<'w>,
47 _entity: Entity,
48 table_row: TableRow,
49 ) -> Self::Item<'w, 's> {
50 let table = fetch
51 .table
52 .unwrap_or_else(|| unsafe { debug_unreachable() });
53
54 ReadTraits {
55 registry: fetch.registry,
56 table,
57 table_row,
58 sparse_sets: fetch.sparse_sets,
59 last_run: fetch.last_run,
60 this_run: fetch.this_run,
61 }
62 }
63}
64unsafe impl<Trait: ?Sized + TraitQuery> ReadOnlyQueryData for All<&Trait> {}
65
66unsafe impl<Trait: ?Sized + TraitQuery> WorldQuery for All<&Trait> {
70 type Fetch<'w> = AllTraitsFetch<'w, Trait>;
71 type State = TraitQueryState<Trait>;
72
73 #[inline]
74 unsafe fn init_fetch<'w>(
75 world: UnsafeWorldCell<'w>,
76 _state: &Self::State,
77 last_run: Tick,
78 this_run: Tick,
79 ) -> Self::Fetch<'w> {
80 unsafe {
81 AllTraitsFetch {
82 registry: world
83 .get_resource()
84 .unwrap_or_else(|| trait_registry_error()),
85 table: None,
86 sparse_sets: &world.storages().sparse_sets,
87 last_run,
88 this_run,
89 }
90 }
91 }
92
93 const IS_DENSE: bool = false;
94
95 #[inline]
96 unsafe fn set_archetype<'w>(
97 fetch: &mut Self::Fetch<'w>,
98 _state: &Self::State,
99 _archetype: &'w bevy_ecs::archetype::Archetype,
100 table: &'w bevy_ecs::storage::Table,
101 ) {
102 fetch.table = Some(table);
103 }
104
105 unsafe fn set_table<'w>(
106 fetch: &mut Self::Fetch<'w>,
107 _state: &Self::State,
108 table: &'w bevy_ecs::storage::Table,
109 ) {
110 fetch.table = Some(table);
111 }
112
113 #[inline]
114 fn update_component_access(state: &Self::State, access: &mut bevy_ecs::query::FilteredAccess) {
115 let mut not_first = false;
116 let mut new_access = access.clone();
117 for &component in &*state.components {
118 assert!(
119 !access.access().has_component_write(component),
120 "&{} conflicts with a previous access in this query. Shared access cannot coincide with exclusive access.",
121 std::any::type_name::<Trait>(),
122 );
123 if not_first {
124 let mut intermediate = access.clone();
125 intermediate.add_component_read(component);
126 new_access.append_or(&intermediate);
127 new_access.extend_access(&intermediate);
128 } else {
129 new_access.and_with(component);
130 new_access.access_mut().add_component_read(component);
131 not_first = true;
132 }
133 }
134 *access = new_access;
135 }
136
137 #[inline]
138 fn init_state(world: &mut World) -> Self::State {
139 TraitQueryState::init(world)
140 }
141
142 #[inline]
143 fn get_state(_: &Components) -> Option<Self::State> {
144 panic!(
146 "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"
147 );
148 }
149
150 #[inline]
151 fn matches_component_set(
152 state: &Self::State,
153 set_contains_id: &impl Fn(ComponentId) -> bool,
154 ) -> bool {
155 state.matches_component_set_any(set_contains_id)
156 }
157
158 #[inline]
159 fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {
160 fetch
161 }
162}
163
164unsafe impl<'a, Trait: ?Sized + TraitQuery> QueryData for All<&'a mut Trait> {
165 type ReadOnly = All<&'a Trait>;
166
167 const IS_READ_ONLY: bool = false;
168
169 type Item<'w, 's> = WriteTraits<'w, Trait>;
170
171 #[inline]
172 fn shrink<'wlong: 'wshort, 'wshort, 's>(
173 item: QueryItem<'wlong, 's, Self>,
174 ) -> QueryItem<'wshort, 's, Self> {
175 item
176 }
177
178 #[inline]
179 unsafe fn fetch<'w, 's>(
180 _state: &'s Self::State,
181 fetch: &mut Self::Fetch<'w>,
182 _entity: Entity,
183 table_row: TableRow,
184 ) -> Self::Item<'w, 's> {
185 let table = fetch
186 .table
187 .unwrap_or_else(|| unsafe { debug_unreachable() });
188
189 WriteTraits {
190 registry: fetch.registry,
191 table,
192 table_row,
193 sparse_sets: fetch.sparse_sets,
194 last_run: fetch.last_run,
195 this_run: fetch.this_run,
196 }
197 }
198}
199
200unsafe impl<Trait: ?Sized + TraitQuery> WorldQuery for All<&mut Trait> {
204 type Fetch<'w> = AllTraitsFetch<'w, Trait>;
205 type State = TraitQueryState<Trait>;
206
207 #[inline]
208 unsafe fn init_fetch<'w>(
209 world: UnsafeWorldCell<'w>,
210 _state: &Self::State,
211 last_run: Tick,
212 this_run: Tick,
213 ) -> Self::Fetch<'w> {
214 unsafe {
215 AllTraitsFetch {
216 registry: world
217 .get_resource()
218 .unwrap_or_else(|| trait_registry_error()),
219 table: None,
220 sparse_sets: &world.storages().sparse_sets,
221 last_run,
222 this_run,
223 }
224 }
225 }
226
227 const IS_DENSE: bool = false;
228
229 #[inline]
230 unsafe fn set_archetype<'w>(
231 fetch: &mut Self::Fetch<'w>,
232 _state: &Self::State,
233 _archetype: &'w bevy_ecs::archetype::Archetype,
234 table: &'w bevy_ecs::storage::Table,
235 ) {
236 fetch.table = Some(table);
237 }
238
239 #[inline]
240 unsafe fn set_table<'w>(
241 fetch: &mut Self::Fetch<'w>,
242 _state: &Self::State,
243 table: &'w bevy_ecs::storage::Table,
244 ) {
245 fetch.table = Some(table);
246 }
247
248 #[inline]
249 fn update_component_access(state: &Self::State, access: &mut bevy_ecs::query::FilteredAccess) {
250 let mut not_first = false;
251 let mut new_access = access.clone();
252 for &component in &*state.components {
253 assert!(
254 !access.access().has_component_write(component),
255 "&mut {} conflicts with a previous access in this query. Mutable component access must be unique.",
256 std::any::type_name::<Trait>(),
257 );
258 if not_first {
259 let mut intermediate = access.clone();
260 intermediate.add_component_write(component);
261 new_access.append_or(&intermediate);
262 new_access.extend_access(&intermediate);
263 } else {
264 new_access.and_with(component);
265 new_access.access_mut().add_component_write(component);
266 not_first = true;
267 }
268 }
269 *access = new_access;
270 }
271
272 #[inline]
273 fn init_state(world: &mut World) -> Self::State {
274 TraitQueryState::init(world)
275 }
276
277 #[inline]
278 fn get_state(_: &Components) -> Option<Self::State> {
279 panic!(
281 "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"
282 );
283 }
284
285 #[inline]
286 fn matches_component_set(
287 state: &Self::State,
288 set_contains_id: &impl Fn(ComponentId) -> bool,
289 ) -> bool {
290 state.matches_component_set_any(set_contains_id)
291 }
292
293 #[inline]
294 fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {
295 fetch
296 }
297}