Skip to content

Commit 5901c9e

Browse files
committed
cleanup
1 parent 2607987 commit 5901c9e

File tree

3 files changed

+42
-25
lines changed

3 files changed

+42
-25
lines changed

crates/bevy_ecs/src/query/state.rs

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ use crate::{
1414
use crate::entity::UniqueEntityEquivalentSlice;
1515

1616
use alloc::vec::Vec;
17-
use core::{fmt, ptr};
17+
use core::{fmt, ops::DerefMut, ptr};
18+
use derive_more::derive::{Deref, DerefMut};
1819
use fixedbitset::FixedBitSet;
1920
use log::warn;
2021
#[cfg(feature = "trace")]
@@ -25,6 +26,12 @@ use super::{
2526
QueryManyUniqueIter, QuerySingleError, ROQueryItem, ReadOnlyQueryData,
2627
};
2728

29+
#[repr(C)]
30+
#[derive(Component, Deref, DerefMut)]
31+
#[component(storage = "SparseSet")]
32+
/// A Internal Wrapper of [`QueryState`] for safety reasons.
33+
pub(crate) struct InternalQueryState<D: QueryData, F: QueryFilter>(QueryState<D, F>);
34+
2835
/// An ID for either a table or an archetype. Used for Query iteration.
2936
///
3037
/// Query iteration is exclusively dense (over tables) or archetypal (over archetypes) based on whether
@@ -60,8 +67,6 @@ pub(super) union StorageId {
6067
/// [`Fetch`]: crate::query::world_query::WorldQuery::Fetch
6168
/// [`Table`]: crate::storage::Table
6269
#[repr(C)]
63-
#[derive(Component)]
64-
#[component(storage = "SparseSet")]
6570
// SAFETY NOTE:
6671
// Do not add any new fields that use the `D` or `F` generic parameters as this may
6772
// make `QueryState::as_transmuted_state` unsound if not done with care.
@@ -1753,6 +1758,31 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
17531758
}
17541759
}
17551760

1761+
impl<D: QueryData + 'static, F: QueryFilter + 'static> QueryState<D, F> {
1762+
/// cache a [`QueryState`] into world.
1763+
pub(crate) fn cached(self, world: &mut World) -> (Entity, ComponentId) {
1764+
let id = world.register_component::<InternalQueryState<D, F>>();
1765+
let e = world.spawn(InternalQueryState(self)).id();
1766+
(e, id)
1767+
}
1768+
1769+
/// fetch a cached [`QueryState`] from world
1770+
pub(crate) unsafe fn fetch_mut_from_cached<'w>(
1771+
cached: (Entity, ComponentId),
1772+
w: UnsafeWorldCell<'w>,
1773+
) -> Option<&'w mut QueryState<D, F>> {
1774+
w.storages()
1775+
.sparse_sets
1776+
.get(cached.1)
1777+
.map(|s| s.get(cached.0))
1778+
.flatten()
1779+
.map(|ptr| {
1780+
ptr.assert_unique()
1781+
.deref_mut::<InternalQueryState<D, F>>()
1782+
.deref_mut()
1783+
})
1784+
}
1785+
}
17561786
impl<D: QueryData, F: QueryFilter> From<QueryBuilder<'_, D, F>> for QueryState<D, F> {
17571787
fn from(mut value: QueryBuilder<D, F>) -> Self {
17581788
QueryState::from_builder(&mut value)

crates/bevy_ecs/src/system/builder.rs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -217,9 +217,7 @@ unsafe impl<'w, 's, D: QueryData + 'static, F: QueryFilter + 'static>
217217
fn build(self, world: &mut World, system_meta: &mut SystemMeta) -> (Entity, ComponentId) {
218218
self.validate_world(world.id());
219219
init_query_param(world, system_meta, &self);
220-
let id = world.register_component::<QueryState<D, F>>();
221-
let e = world.spawn(self).id();
222-
(e, id)
220+
self.cached(world)
223221
}
224222
}
225223

@@ -300,9 +298,7 @@ unsafe impl<
300298
(self.0)(&mut builder);
301299
let state = builder.build();
302300
init_query_param(world, system_meta, &state);
303-
let id = world.register_component::<QueryState<D, F>>();
304-
let e = world.spawn(state).id();
305-
(e, id)
301+
state.cached(world)
306302
}
307303
}
308304

@@ -971,9 +967,9 @@ mod tests {
971967

972968
#[derive(SystemParam)]
973969
#[system_param(builder)]
974-
struct CustomParam<'w> {
970+
struct CustomParam<'w, 's> {
975971
query: Query<'w, 'w, ()>,
976-
local: Local<usize>,
972+
local: Local<'s, usize>,
977973
}
978974

979975
#[test]

crates/bevy_ecs/src/system/system_param.rs

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ use crate::{
66
component::{ComponentId, ComponentTicks, Components, Tick},
77
entity::{Entities, Entity},
88
query::{
9-
Access, DebugCheckedUnwrap, FilteredAccess, FilteredAccessSet, QueryData, QueryFilter,
10-
QuerySingleError, QueryState, ReadOnlyQueryData,
9+
Access, FilteredAccess, FilteredAccessSet, QueryData, QueryFilter, QuerySingleError,
10+
QueryState, ReadOnlyQueryData,
1111
},
1212
resource::Resource,
1313
storage::ResourceData,
@@ -327,9 +327,7 @@ unsafe impl<D: QueryData + 'static, F: QueryFilter + 'static> SystemParam for Qu
327327
fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State {
328328
let state: QueryState<D, F> = QueryState::new(world);
329329
init_query_param(world, system_meta, &state);
330-
let e = world.spawn(state).id();
331-
let id = world.register_component::<QueryState<D, F>>();
332-
(e, id)
330+
state.cached(world)
333331
}
334332

335333
#[inline]
@@ -339,15 +337,8 @@ unsafe impl<D: QueryData + 'static, F: QueryFilter + 'static> SystemParam for Qu
339337
world: UnsafeWorldCell<'w>,
340338
change_tick: Tick,
341339
) -> Self::Item<'w, 'w> {
342-
let state = world
343-
.storages()
344-
.sparse_sets
345-
.get(state.1)
346-
.debug_checked_unwrap()
347-
.get(state.0)
348-
.debug_checked_unwrap()
349-
.assert_unique()
350-
.deref_mut::<QueryState<D, F>>();
340+
let state = QueryState::fetch_mut_from_cached(*state, world)
341+
.expect("cached querystate entity not found");
351342
// SAFETY: We have registered all of the query's world accesses,
352343
// so the caller ensures that `world` has permission to access any
353344
// world data that the query needs.

0 commit comments

Comments
 (0)