Skip to content

Commit

Permalink
New SystemParams: Archetypes, Components, Entities, Bundles
Browse files Browse the repository at this point in the history
  • Loading branch information
cart committed Feb 26, 2021
1 parent 9a39f06 commit 32be92b
Show file tree
Hide file tree
Showing 3 changed files with 178 additions and 3 deletions.
15 changes: 15 additions & 0 deletions crates/bevy_ecs/src/core/bundle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,21 @@ impl BundleInfo {
bundle_component += 1;
});
}

#[inline]
pub fn id(&self) -> BundleId {
self.id
}

#[inline]
pub fn components(&self) -> &[ComponentId] {
&self.component_ids
}

#[inline]
pub fn storage_types(&self) -> &[StorageType] {
&self.storage_types
}
}

#[derive(Default)]
Expand Down
49 changes: 48 additions & 1 deletion crates/bevy_ecs/src/system/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ pub use system_param::*;
#[cfg(test)]
mod tests {
use crate::{
core::{Added, Changed, Entity, FromWorld, Mutated, Or, With, Without, World},
core::{
Added, Archetypes, Bundles, Changed, Components, Entities, Entity, FromWorld, Mutated,
Or, With, Without, World,
},
schedule::{Schedule, Stage, SystemStage},
system::{IntoSystem, Local, Query, QuerySet, RemovedComponents, Res, ResMut, System},
};
Expand Down Expand Up @@ -391,6 +394,50 @@ mod tests {
sys.system().config(|config| config.0 = Some(42)),
);

// ensure the system actually ran
assert_eq!(*world.get_resource::<bool>().unwrap(), true);
}
#[test]
fn world_collections_system() {
let mut world = World::default();
world.insert_resource(false);
world.spawn().insert_bundle((42, true));
fn sys(
archetypes: &Archetypes,
components: &Components,
entities: &Entities,
bundles: &Bundles,
query: Query<Entity, With<i32>>,
mut modified: ResMut<bool>,
) {
assert_eq!(query.iter().count(), 1, "entity exists");
for entity in query.iter() {
let location = entities.get(entity).unwrap();
let archetype = archetypes.get(location.archetype_id).unwrap();
let archetype_components = archetype.components().collect::<Vec<_>>();
let bundle_id = bundles
.get_id(std::any::TypeId::of::<(i32, bool)>())
.expect("Bundle used to spawn entity should exist");
let bundle_info = bundles.get(bundle_id).unwrap();
let mut bundle_components =
bundle_info.components().iter().cloned().collect::<Vec<_>>();
bundle_components.sort();
for component_id in bundle_components.iter() {
assert!(
components.get_info(*component_id).is_some(),
"every bundle component exists in Components"
);
}
assert_eq!(
bundle_components, archetype_components,
"entity's bundle components exactly match entity's archetype components"
);
}
*modified = true;
}

run_system(&mut world, sys.system());

// ensure the system actually ran
assert_eq!(*world.get_resource::<bool>().unwrap(), true);
}
Expand Down
117 changes: 115 additions & 2 deletions crates/bevy_ecs/src/system/system_param.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use crate::{
core::{
Archetype, Component, ComponentFlags, ComponentId, Entity, FilterFetch, FilteredAccess,
FilteredAccessSet, FromWorld, Or, QueryState, World, WorldQuery,
Archetype, Archetypes, Bundles, Component, ComponentFlags, ComponentId, Components,
Entities, Entity, FilterFetch, FilteredAccess, FilteredAccessSet, FromWorld, Or,
QueryState, World, WorldQuery,
},
system::{CommandQueue, Commands, Query, SystemState},
};
Expand Down Expand Up @@ -567,6 +568,118 @@ impl<'a, T: 'static> SystemParamFetch<'a> for NonSendMutState<T> {

pub struct OrState<T>(T);

impl<'a> SystemParam for &'a Archetypes {
type Fetch = ArchetypesState;
}

pub struct ArchetypesState;

// SAFE: no component value access
unsafe impl SystemParamState for ArchetypesState {
type Config = ();

fn init(_world: &mut World, _system_state: &mut SystemState, _config: Self::Config) -> Self {
Self
}
}

impl<'a> SystemParamFetch<'a> for ArchetypesState {
type Item = &'a Archetypes;

#[inline]
unsafe fn get_param(
_state: &'a mut Self,
_system_state: &'a SystemState,
world: &'a World,
) -> Option<Self::Item> {
Some(world.archetypes())
}
}

impl<'a> SystemParam for &'a Components {
type Fetch = ComponentsState;
}

pub struct ComponentsState;

// SAFE: no component value access
unsafe impl SystemParamState for ComponentsState {
type Config = ();

fn init(_world: &mut World, _system_state: &mut SystemState, _config: Self::Config) -> Self {
Self
}
}

impl<'a> SystemParamFetch<'a> for ComponentsState {
type Item = &'a Components;

#[inline]
unsafe fn get_param(
_state: &'a mut Self,
_system_state: &'a SystemState,
world: &'a World,
) -> Option<Self::Item> {
Some(world.components())
}
}

impl<'a> SystemParam for &'a Entities {
type Fetch = EntitiesState;
}

pub struct EntitiesState;

// SAFE: no component value access
unsafe impl SystemParamState for EntitiesState {
type Config = ();

fn init(_world: &mut World, _system_state: &mut SystemState, _config: Self::Config) -> Self {
Self
}
}

impl<'a> SystemParamFetch<'a> for EntitiesState {
type Item = &'a Entities;

#[inline]
unsafe fn get_param(
_state: &'a mut Self,
_system_state: &'a SystemState,
world: &'a World,
) -> Option<Self::Item> {
Some(world.entities())
}
}

impl<'a> SystemParam for &'a Bundles {
type Fetch = BundlesState;
}

pub struct BundlesState;

// SAFE: no component value access
unsafe impl SystemParamState for BundlesState {
type Config = ();

fn init(_world: &mut World, _system_state: &mut SystemState, _config: Self::Config) -> Self {
Self
}
}

impl<'a> SystemParamFetch<'a> for BundlesState {
type Item = &'a Bundles;

#[inline]
unsafe fn get_param(
_state: &'a mut Self,
_system_state: &'a SystemState,
world: &'a World,
) -> Option<Self::Item> {
Some(world.bundles())
}
}

macro_rules! impl_system_param_tuple {
($($param: ident),*) => {
impl<$($param: SystemParam),*> SystemParam for ($($param,)*) {
Expand Down

0 comments on commit 32be92b

Please sign in to comment.