some system_fn renaming and add system examples

This commit is contained in:
Carter Anderson 2020-04-28 13:46:07 -07:00
parent 713c4a6056
commit f1a03a7a3a
6 changed files with 111 additions and 46 deletions

View file

@ -1,8 +1,8 @@
use legion::{ use legion::{
filter::EntityFilter, filter::EntityFilter,
prelude::{ prelude::{
into_resource_system, into_system, IntoQuery, ResourceSet, Resources, Runnable, into_resource_system, IntoQuery, ResourceSet, Resources, Runnable,
Schedulable, World, Schedulable, World, into_resource_for_each_system, into_for_each_system,
}, },
query::{DefaultFilter, View}, query::{DefaultFilter, View},
}; };
@ -34,7 +34,17 @@ where
} }
impl System { impl System {
pub fn resource_for<'a, Q, F, R, X>(name: &'static str, system: F) -> Self pub fn for_each<'a, Q, F, R>(name: &'static str, system: F) -> Self
where
Q: IntoQuery + DefaultFilter<Filter = R>,
<Q as View<'a>>::Iter: Iterator<Item = Q> + 'a,
F: FnMut(Q) + Send + Sync + 'static,
R: EntityFilter + Sync + 'static,
{
into_for_each_system(name, system).into()
}
pub fn resource_for_each<'a, Q, F, R, X>(name: &'static str, system: F) -> Self
where where
Q: IntoQuery + DefaultFilter<Filter = R>, Q: IntoQuery + DefaultFilter<Filter = R>,
<Q as View<'a>>::Iter: Iterator<Item = Q> + 'a, <Q as View<'a>>::Iter: Iterator<Item = Q> + 'a,
@ -42,7 +52,7 @@ impl System {
R: EntityFilter + Sync + 'static, R: EntityFilter + Sync + 'static,
X: ResourceSet<PreparedResources = X> + 'static, X: ResourceSet<PreparedResources = X> + 'static,
{ {
into_system(name, system).into() into_resource_for_each_system(name, system).into()
} }
pub fn resource<'a, F, X>(name: &'static str, system: F) -> Self pub fn resource<'a, F, X>(name: &'static str, system: F) -> Self

View file

@ -16,6 +16,6 @@ pub mod prelude {
resource::{ResourceSet, Resources, PreparedRead as Resource, PreparedWrite as ResourceMut}, resource::{ResourceSet, Resources, PreparedRead as Resource, PreparedWrite as ResourceMut},
schedule::{Executor, Runnable, Schedulable, Schedule}, schedule::{Executor, Runnable, Schedulable, Schedule},
System, SystemBuilder, System, SystemBuilder,
into_system, into_resource_system into_for_each_system, into_resource_system, into_resource_for_each_system,
}; };
} }

View file

@ -3,17 +3,56 @@ use crate::{
schedule::{ArchetypeAccess, Schedulable}, schedule::{ArchetypeAccess, Schedulable},
Access, System, SystemAccess, SystemFnWrapper, SystemQuery, Access, System, SystemAccess, SystemFnWrapper, SystemQuery,
}; };
use bit_set::BitSet;
use fxhash::FxHashMap; use fxhash::FxHashMap;
use legion_core::{ use legion_core::{
borrow::{AtomicRefCell}, borrow::AtomicRefCell,
filter::EntityFilter, filter::EntityFilter,
query::{DefaultFilter, IntoQuery, View}, query::{DefaultFilter, IntoQuery, View},
storage::{ComponentTypeId}, storage::ComponentTypeId,
}; };
use std::marker::PhantomData; use std::marker::PhantomData;
use bit_set::BitSet;
pub fn into_system<'a, Q, F, R, X>(name: &'static str, mut system: F) -> Box<dyn Schedulable> pub fn into_for_each_system<'a, Q, F, R>(name: &'static str, mut system: F) -> Box<dyn Schedulable>
where
Q: IntoQuery + DefaultFilter<Filter = R>,
<Q as View<'a>>::Iter: Iterator<Item = Q> + 'a,
F: FnMut(Q) + Send + Sync + 'static,
R: EntityFilter + Sync + 'static,
{
let resource_access: Access<ResourceTypeId> = Access::default();
let mut component_access: Access<ComponentTypeId> = Access::default();
component_access.reads.extend(Q::read_types().iter());
component_access.writes.extend(Q::write_types().iter());
let run_fn = SystemFnWrapper(
move |_, world, _, query: &mut SystemQuery<Q, <Q as DefaultFilter>::Filter>| {
for components in query.iter_mut(world) {
system(components);
}
},
PhantomData,
);
Box::new(System {
name: name.into(),
queries: AtomicRefCell::new(Q::query()),
access: SystemAccess {
resources: resource_access,
components: component_access,
tags: Access::default(),
},
archetypes: ArchetypeAccess::Some(BitSet::default()),
_resources: PhantomData::<()>,
command_buffer: FxHashMap::default(),
run_fn: AtomicRefCell::new(run_fn),
})
}
pub fn into_resource_for_each_system<'a, Q, F, R, X>(
name: &'static str,
mut system: F,
) -> Box<dyn Schedulable>
where where
Q: IntoQuery + DefaultFilter<Filter = R>, Q: IntoQuery + DefaultFilter<Filter = R>,
<Q as View<'a>>::Iter: Iterator<Item = Q> + 'a, <Q as View<'a>>::Iter: Iterator<Item = Q> + 'a,
@ -67,10 +106,7 @@ where
let component_access: Access<ComponentTypeId> = Access::default(); let component_access: Access<ComponentTypeId> = Access::default();
let run_fn = SystemFnWrapper( let run_fn = SystemFnWrapper(
move |_, move |_, _, resources: &mut X, _| {
_,
resources: &mut X,
_| {
system(resources); system(resources);
}, },
PhantomData, PhantomData,
@ -93,8 +129,8 @@ where
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::into_system;
use crate::{ use crate::{
into_resource_for_each_system,
resource::{PreparedRead, PreparedWrite, Resources}, resource::{PreparedRead, PreparedWrite, Resources},
}; };
use legion_core::{ use legion_core::{
@ -113,15 +149,13 @@ mod tests {
#[test] #[test]
fn test_system_fn() { fn test_system_fn() {
fn read_write_system(_: &mut (), (_x, mut y): (Ref<X>, RefMut<Y>)) { fn read_write_system(_: &mut (), (_x, mut y): (Ref<X>, RefMut<Y>)) { y.0 += 1; }
y.0 += 1;
}
let mut world = World::new(); let mut world = World::new();
let mut resources = Resources::default(); let mut resources = Resources::default();
world.insert((), vec![(X(1), Y(1)), (X(2), Y(2))]); world.insert((), vec![(X(1), Y(1)), (X(2), Y(2))]);
let mut system = into_system("read_write", read_write_system); let mut system = into_resource_for_each_system("read_write", read_write_system);
system.run(&mut world, &mut resources); system.run(&mut world, &mut resources);
} }
@ -154,7 +188,7 @@ mod tests {
resources.insert(A(0)); resources.insert(A(0));
resources.insert(B(1)); resources.insert(B(1));
world.insert((), vec![(X(2), Y(3)), (X(4), Y(5))]); world.insert((), vec![(X(2), Y(3)), (X(4), Y(5))]);
let mut my_system = into_system("read_resources", my_system); let mut my_system = into_resource_for_each_system("read_resources", my_system);
my_system.run(&mut world, &mut resources); my_system.run(&mut world, &mut resources);
} }
} }

View file

@ -9,7 +9,7 @@ fn main() {
..Default::default() ..Default::default()
}) })
.add_startup_system(setup) .add_startup_system(setup)
.add_system(System::resource_for("move", move_system)) .add_system(System::resource_for_each("move", move_system))
.run(); .run();
} }

View file

@ -1,34 +1,56 @@
use bevy::{ use bevy::prelude::*;
input::mouse::{MouseButtonInput, MouseMotion},
prelude::*,
};
/// Illustrates the different ways you can declare systems
fn main() { fn main() {
App::build() App::build()
.add_default_plugins() .add_default_plugins()
.add_system_init(mouse_input_system) .add_event::<MyEvent>()
.add_startup_system(setup)
.add_system_init(system_b)
.add_system(System::for_each("system_a", system_a))
.run(); .run();
} }
/// prints out mouse events as they come in struct MyEvent(usize);
pub fn mouse_input_system(resources: &mut Resources) -> Box<dyn Schedulable> {
let mut mouse_button_input_event_reader = resources.get_event_reader::<MouseButtonInput>();
let mut mouse_motion_event_reader = resources.get_event_reader::<MouseMotion>();
SystemBuilder::new("mouse_input")
.read_resource::<Events<MouseButtonInput>>()
.read_resource::<Events<MouseMotion>>()
.build(
move |_command_buffer,
_world,
(mouse_button_input_events, mouse_motion_events),
_queries| {
for event in mouse_button_input_event_reader.iter(&mouse_button_input_events) {
println!("{:?}", event);
}
for event in mouse_motion_event_reader.iter(&mouse_motion_events) { // resources
println!("{:?}", event); struct A(usize);
}
}, // components
) struct X(usize);
struct Y(usize);
// add our resources and entities
fn setup(world: &mut World, resources: &mut Resources) {
resources.insert(A(0));
world.insert((), vec![(X(0), Y(1)), (X(2), Y(3))]);
}
fn system_a((x, y): (Ref<X>, RefMut<Y>)) {
}
// fn system_a(x: Ref<X>, mut y: RefMut<Y>) {
// }
// fn system_a((my_events, a): &mut (Resource<Events<MyEvent>>, Resource<A>), (x, mut y): (Ref<X>, RefMut<Y>)) {
// }
fn system_b(resources: &mut Resources) -> Box<dyn Schedulable> {
let mut my_event_reader = resources.get_event_reader::<MyEvent>();
SystemBuilder::new("example")
.read_resource::<Events<MyEvent>>()
.write_resource::<A>()
.with_query(<(Read<X>, Write<Y>)>::query())
.build(move |_command_buffer, world, (my_events, ref mut a), query| {
for event in my_event_reader.iter(&my_events) {
a.0 += event.0;
println!("modified resource A with event: {}", event.0);
}
for (x, mut y) in query.iter_mut(world) {
y.0 += 1;
println!("processed entity: {} {}", x.0, y.0);
}
})
} }

View file

@ -55,7 +55,6 @@ pub use legion::{
resource::{ResourceSet, Resources, PreparedRead as Resource, PreparedWrite as ResourceMut}, resource::{ResourceSet, Resources, PreparedRead as Resource, PreparedWrite as ResourceMut},
schedule::{Executor, Runnable, Schedulable, Schedule}, schedule::{Executor, Runnable, Schedulable, Schedule},
SubWorld, SystemBuilder, SubWorld, SystemBuilder,
into_system, into_resource_system
}, },
world::{Universe, World}, world::{Universe, World},
}; };