System Inputs, Outputs, Chaining, and Registration Ergo (#876)

System Inputs, Outputs, Chaining, and Registration Ergo
This commit is contained in:
Carter Anderson 2020-11-16 18:18:00 -08:00 committed by GitHub
parent 50c7e229b2
commit 3a6f6de277
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
95 changed files with 595 additions and 461 deletions

View file

@ -194,6 +194,10 @@ path = "examples/ecs/event.rs"
name = "startup_system"
path = "examples/ecs/startup_system.rs"
[[example]]
name = "system_chaining"
path = "examples/ecs/system_chaining.rs"
[[example]]
name = "ecs_guide"
path = "examples/ecs/ecs_guide.rs"

View file

@ -95,81 +95,40 @@ impl AppBuilder {
self
}
pub fn add_system(&mut self, system: Box<dyn System>) -> &mut Self {
pub fn add_system<S, Params, IntoS>(&mut self, system: IntoS) -> &mut Self
where
S: System<Input = (), Output = ()>,
IntoS: IntoSystem<Params, S>,
{
self.add_system_to_stage(stage::UPDATE, system)
}
pub fn add_systems(&mut self, systems: Vec<Box<dyn System>>) -> &mut Self {
self.add_systems_to_stage(stage::UPDATE, systems)
}
pub fn init_system(
&mut self,
build: impl FnMut(&mut Resources) -> Box<dyn System>,
) -> &mut Self {
self.init_system_to_stage(stage::UPDATE, build)
}
pub fn init_system_to_stage(
&mut self,
stage: &'static str,
mut build: impl FnMut(&mut Resources) -> Box<dyn System>,
) -> &mut Self {
let system = build(&mut self.app.resources);
self.add_system_to_stage(stage, system)
}
pub fn add_startup_system_to_stage(
pub fn add_startup_system_to_stage<S, Params, IntoS>(
&mut self,
stage_name: &'static str,
system: Box<dyn System>,
) -> &mut Self {
system: IntoS,
) -> &mut Self
where
S: System<Input = (), Output = ()>,
IntoS: IntoSystem<Params, S>,
{
self.app
.startup_schedule
.add_system_to_stage(stage_name, system);
self
}
pub fn add_startup_systems_to_stage(
&mut self,
stage_name: &'static str,
systems: Vec<Box<dyn System>>,
) -> &mut Self {
for system in systems {
self.app
.startup_schedule
.add_system_to_stage(stage_name, system);
}
self
}
pub fn add_startup_system(&mut self, system: Box<dyn System>) -> &mut Self {
pub fn add_startup_system<S, Params, IntoS>(&mut self, system: IntoS) -> &mut Self
where
S: System<Input = (), Output = ()>,
IntoS: IntoSystem<Params, S>,
{
self.app
.startup_schedule
.add_system_to_stage(startup_stage::STARTUP, system);
self
}
pub fn add_startup_systems(&mut self, systems: Vec<Box<dyn System>>) -> &mut Self {
self.add_startup_systems_to_stage(startup_stage::STARTUP, systems)
}
pub fn init_startup_system(
&mut self,
build: impl FnMut(&mut Resources) -> Box<dyn System>,
) -> &mut Self {
self.init_startup_system_to_stage(startup_stage::STARTUP, build)
}
pub fn init_startup_system_to_stage(
&mut self,
stage: &'static str,
mut build: impl FnMut(&mut Resources) -> Box<dyn System>,
) -> &mut Self {
let system = build(&mut self.app.resources);
self.add_startup_system_to_stage(stage, system)
}
pub fn add_default_stages(&mut self) -> &mut Self {
self.add_startup_stage(startup_stage::PRE_STARTUP)
.add_startup_stage(startup_stage::STARTUP)
@ -183,34 +142,31 @@ impl AppBuilder {
.add_stage(stage::LAST)
}
pub fn add_system_to_stage(
pub fn add_system_to_stage<S, Params, IntoS>(
&mut self,
stage_name: &'static str,
system: Box<dyn System>,
) -> &mut Self {
system: IntoS,
) -> &mut Self
where
S: System<Input = (), Output = ()>,
IntoS: IntoSystem<Params, S>,
{
self.app.schedule.add_system_to_stage(stage_name, system);
self
}
pub fn add_system_to_stage_front(
pub fn add_system_to_stage_front<S, Params, IntoS>(
&mut self,
stage_name: &'static str,
system: Box<dyn System>,
) -> &mut Self {
system: IntoS,
) -> &mut Self
where
S: System<Input = (), Output = ()>,
IntoS: IntoSystem<Params, S>,
{
self.app
.schedule
.add_system_to_stage_front(stage_name, system);
self
}
pub fn add_systems_to_stage(
&mut self,
stage_name: &'static str,
systems: Vec<Box<dyn System>>,
) -> &mut Self {
for system in systems {
self.app.schedule.add_system_to_stage(stage_name, system);
}
.add_system_to_stage_front(stage_name, system.system());
self
}
@ -219,7 +175,7 @@ impl AppBuilder {
T: Send + Sync + 'static,
{
self.add_resource(Events::<T>::default())
.add_system_to_stage(stage::EVENT, Events::<T>::update_system.system())
.add_system_to_stage(stage::EVENT, Events::<T>::update_system)
}
/// Adds a resource to the current [App] and overwrites any resource previously added of the same type.

View file

@ -2,7 +2,7 @@ use crate::{
update_asset_storage_system, Asset, AssetLoader, AssetServer, Handle, HandleId, RefChange,
};
use bevy_app::{prelude::Events, AppBuilder};
use bevy_ecs::{FromResources, IntoSystem, ResMut};
use bevy_ecs::{FromResources, ResMut};
use bevy_type_registry::RegisterType;
use bevy_utils::HashMap;
use crossbeam_channel::Sender;
@ -219,14 +219,8 @@ impl AddAsset for AppBuilder {
self.add_resource(assets)
.register_component::<Handle<T>>()
.add_system_to_stage(
super::stage::ASSET_EVENTS,
Assets::<T>::asset_event_system.system(),
)
.add_system_to_stage(
crate::stage::LOAD_ASSETS,
update_asset_storage_system::<T>.system(),
)
.add_system_to_stage(super::stage::ASSET_EVENTS, Assets::<T>::asset_event_system)
.add_system_to_stage(crate::stage::LOAD_ASSETS, update_asset_storage_system::<T>)
.add_event::<AssetEvent<T>>()
}

View file

@ -31,7 +31,6 @@ pub mod prelude {
}
use bevy_app::{prelude::Plugin, AppBuilder};
use bevy_ecs::IntoSystem;
use bevy_type_registry::RegisterType;
/// Adds support for Assets to an App. Assets are typed collections with change tracking, which are added as App Resources.
@ -80,13 +79,13 @@ impl Plugin for AssetPlugin {
.register_property::<HandleId>()
.add_system_to_stage(
bevy_app::stage::PRE_UPDATE,
asset_server::free_unused_assets_system.system(),
asset_server::free_unused_assets_system,
);
#[cfg(all(
feature = "filesystem_watcher",
all(not(target_arch = "wasm32"), not(target_os = "android"))
))]
app.add_system_to_stage(stage::LOAD_ASSETS, io::filesystem_watcher_system.system());
app.add_system_to_stage(stage::LOAD_ASSETS, io::filesystem_watcher_system);
}
}

View file

@ -12,7 +12,6 @@ pub mod prelude {
use bevy_app::prelude::*;
use bevy_asset::AddAsset;
use bevy_ecs::IntoThreadLocalSystem;
/// Adds support for audio playback to an App
#[derive(Default)]
@ -24,9 +23,6 @@ impl Plugin for AudioPlugin {
.add_asset::<AudioSource>()
.init_asset_loader::<Mp3Loader>()
.init_resource::<Audio<AudioSource>>()
.add_system_to_stage(
stage::POST_UPDATE,
play_queued_audio_system::<AudioSource>.thread_local_system(),
);
.add_system_to_stage(stage::POST_UPDATE, play_queued_audio_system::<AudioSource>);
}
}

View file

@ -15,7 +15,6 @@ pub mod prelude {
}
use bevy_app::prelude::*;
use bevy_ecs::prelude::*;
use bevy_math::{Mat3, Mat4, Quat, Vec2, Vec3};
use bevy_type_registry::RegisterType;
@ -40,8 +39,8 @@ impl Plugin for CorePlugin {
.register_property::<Mat4>()
.register_property::<Quat>()
.register_property::<Option<String>>()
.add_system_to_stage(stage::FIRST, time_system.system())
.add_system_to_stage(stage::FIRST, timer_system.system())
.add_system_to_stage(stage::PRE_UPDATE, entity_labels_system.system());
.add_system_to_stage(stage::FIRST, time_system)
.add_system_to_stage(stage::FIRST, timer_system)
.add_system_to_stage(stage::PRE_UPDATE, entity_labels_system);
}
}

View file

@ -1,7 +1,7 @@
use crate::{Diagnostic, DiagnosticId, Diagnostics};
use bevy_app::prelude::*;
use bevy_core::Time;
use bevy_ecs::{IntoSystem, Res, ResMut};
use bevy_ecs::{Res, ResMut};
/// Adds "frame time" diagnostic to an App, specifically "frame time", "fps" and "frame count"
#[derive(Default)]
@ -13,9 +13,9 @@ pub struct FrameTimeDiagnosticsState {
impl Plugin for FrameTimeDiagnosticsPlugin {
fn build(&self, app: &mut bevy_app::AppBuilder) {
app.add_startup_system(Self::setup_system.system())
app.add_startup_system(Self::setup_system)
.add_resource(FrameTimeDiagnosticsState { frame_count: 0.0 })
.add_system(Self::diagnostic_system.system());
.add_system(Self::diagnostic_system);
}
}

View file

@ -1,7 +1,7 @@
use super::{Diagnostic, DiagnosticId, Diagnostics};
use bevy_app::prelude::*;
use bevy_core::{Time, Timer};
use bevy_ecs::{IntoSystem, Res, ResMut};
use bevy_ecs::{Res, ResMut};
use std::time::Duration;
/// An App Plugin that prints diagnostics to the console
@ -35,12 +35,9 @@ impl Plugin for PrintDiagnosticsPlugin {
});
if self.debug {
app.add_system_to_stage(
stage::POST_UPDATE,
Self::print_diagnostics_debug_system.system(),
);
app.add_system_to_stage(stage::POST_UPDATE, Self::print_diagnostics_debug_system);
} else {
app.add_system_to_stage(stage::POST_UPDATE, Self::print_diagnostics_system.system());
app.add_system_to_stage(stage::POST_UPDATE, Self::print_diagnostics_system);
}
}
}

View file

@ -408,23 +408,24 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
}
let generics = ast.generics;
let (impl_generics, ty_generics, _where_clause) = generics.split_for_impl();
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
let struct_name = &ast.ident;
TokenStream::from(quote! {
impl #impl_generics #path::SystemParam for #struct_name#ty_generics {
impl #impl_generics #path::SystemParam<()> for #struct_name#ty_generics #where_clause {
fn init(system_state: &mut #path::SystemState, world: &#path::World, resources: &mut #path::Resources) {
#(<#field_types>::init(system_state, world, resources);)*
#(<#field_types as SystemParam<()>>::init(system_state, world, resources);)*
}
unsafe fn get_param(
input: &mut Option<()>,
system_state: &mut #path::SystemState,
world: &#path::World,
resources: &#path::Resources,
) -> Option<Self> {
Some(#struct_name {
#(#fields: <#field_types>::get_param(system_state, world, resources)?,)*
#(#fields: <#field_types as SystemParam<()>>::get_param(input, system_state, world, resources)?,)*
#(#ignored_fields: <#ignored_field_types>::default(),)*
})
}

View file

@ -14,8 +14,8 @@ pub mod prelude {
pub use crate::{
core::WorldBuilderSource,
resource::{ChangedRes, FromResources, Local, Res, ResMut, Resource, Resources},
system::{Commands, IntoSystem, IntoThreadLocalSystem, Query, System},
Added, Bundle, Changed, Component, Entity, Mut, Mutated, Or, QuerySet, Ref, RefMut, With,
Without, World,
system::{Commands, IntoSystem, Query, System},
Added, Bundle, Changed, Component, Entity, In, IntoChainSystem, Mut, Mutated, Or, QuerySet,
Ref, RefMut, With, Without, World,
};
}

View file

@ -1,10 +1,10 @@
use super::FromResources;
use crate::{Resource, ResourceIndex, Resources, SystemId};
use core::{
use std::{
marker::PhantomData,
ops::{Deref, DerefMut},
ptr::NonNull,
};
use std::marker::PhantomData;
// TODO: align TypeAccess api with Query::Fetch

View file

@ -147,7 +147,7 @@ impl ExecutorStage {
pub fn prepare_to_next_thread_local(
&mut self,
world: &World,
systems: &mut [Box<dyn System>],
systems: &mut [Box<dyn System<Input = (), Output = ()>>],
schedule_changed: bool,
next_thread_local_index: usize,
) -> Range<usize> {
@ -329,7 +329,7 @@ impl ExecutorStage {
&self,
world: &World,
resources: &Resources,
systems: &mut [Box<dyn System>],
systems: &mut [Box<dyn System<Input = (), Output = ()>>],
prepared_system_range: Range<usize>,
compute_pool: &TaskPool,
) {
@ -402,7 +402,10 @@ impl ExecutorStage {
#[cfg(feature = "trace")]
let _system_guard = system_span.enter();
system.run(world_ref, resources_ref);
// SAFETY: scheduler ensures safe world / resource access
unsafe {
system.run_unsafe((), world_ref, resources_ref);
}
}
// Notify dependents that this task is done
@ -419,7 +422,7 @@ impl ExecutorStage {
&mut self,
world: &mut World,
resources: &mut Resources,
systems: &mut [Box<dyn System>],
systems: &mut [Box<dyn System<Input = (), Output = ()>>],
schedule_changed: bool,
) {
let start_archetypes_generation = world.archetypes_generation();
@ -499,7 +502,7 @@ impl ExecutorStage {
#[cfg(feature = "trace")]
let _system_guard = system_span.enter();
system.run(world, resources);
system.run((), world, resources);
system.run_thread_local(world, resources);
}
@ -552,7 +555,7 @@ mod tests {
use crate::{
resource::{Res, ResMut, Resources},
schedule::Schedule,
system::{IntoSystem, IntoThreadLocalSystem, Query},
system::Query,
Commands, Entity, World,
};
use bevy_tasks::{ComputeTaskPool, TaskPool};
@ -589,8 +592,8 @@ mod tests {
assert_eq!(1, entities.iter().count());
}
schedule.add_system_to_stage("PreArchetypeChange", insert.system());
schedule.add_system_to_stage("PostArchetypeChange", read.system());
schedule.add_system_to_stage("PreArchetypeChange", insert);
schedule.add_system_to_stage("PostArchetypeChange", read);
let mut executor = ParallelExecutor::default();
schedule.initialize(&mut world, &mut resources);
@ -620,8 +623,8 @@ mod tests {
assert_eq!(1, entities.iter().count());
}
schedule.add_system_to_stage("update", insert.thread_local_system());
schedule.add_system_to_stage("update", read.system());
schedule.add_system_to_stage("update", insert);
schedule.add_system_to_stage("update", read);
schedule.initialize(&mut world, &mut resources);
let mut executor = ParallelExecutor::default();
@ -691,10 +694,10 @@ mod tests {
completed_systems.insert(READ_U64_SYSTEM_NAME);
}
schedule.add_system_to_stage("A", read_u32.system());
schedule.add_system_to_stage("A", write_float.system());
schedule.add_system_to_stage("A", read_u32_write_u64.system());
schedule.add_system_to_stage("A", read_u64.system());
schedule.add_system_to_stage("A", read_u32);
schedule.add_system_to_stage("A", write_float);
schedule.add_system_to_stage("A", read_u32_write_u64);
schedule.add_system_to_stage("A", read_u64);
// B systems
@ -722,9 +725,9 @@ mod tests {
completed_systems.insert(WRITE_F32_SYSTEM_NAME);
}
schedule.add_system_to_stage("B", write_u64.system());
schedule.add_system_to_stage("B", thread_local_system.thread_local_system());
schedule.add_system_to_stage("B", write_f32.system());
schedule.add_system_to_stage("B", write_u64);
schedule.add_system_to_stage("B", thread_local_system);
schedule.add_system_to_stage("B", write_f32);
// C systems
@ -759,10 +762,10 @@ mod tests {
completed_systems.insert(WRITE_F64_RES_SYSTEM_NAME);
}
schedule.add_system_to_stage("C", read_f64_res.system());
schedule.add_system_to_stage("C", read_isize_res.system());
schedule.add_system_to_stage("C", read_isize_write_f64_res.system());
schedule.add_system_to_stage("C", write_f64_res.system());
schedule.add_system_to_stage("C", read_f64_res);
schedule.add_system_to_stage("C", read_isize_res);
schedule.add_system_to_stage("C", read_isize_write_f64_res);
schedule.add_system_to_stage("C", write_f64_res);
schedule.initialize(&mut world, &mut resources);
fn run_executor_and_validate(

View file

@ -1,7 +1,7 @@
use crate::{
resource::Resources,
system::{System, SystemId, ThreadLocalExecution},
World,
IntoSystem, World,
};
use bevy_utils::{HashMap, HashSet};
use std::{borrow::Cow, fmt};
@ -11,7 +11,7 @@ use std::{borrow::Cow, fmt};
/// They are run on a given [World] and [Resources] reference.
#[derive(Default)]
pub struct Schedule {
pub(crate) stages: HashMap<Cow<'static, str>, Vec<Box<dyn System>>>,
pub(crate) stages: HashMap<Cow<'static, str>, Vec<Box<dyn System<Input = (), Output = ()>>>>,
pub(crate) stage_order: Vec<Cow<'static, str>>,
pub(crate) system_ids: HashSet<SystemId>,
generation: usize,
@ -96,12 +96,32 @@ impl Schedule {
self.stage_order.insert(target_index, stage);
}
pub fn add_system_to_stage(
pub fn add_system_to_stage<S, Params, IntoS>(
&mut self,
stage_name: impl Into<Cow<'static, str>>,
system: Box<dyn System>,
) -> &mut Self {
let stage_name = stage_name.into();
system: IntoS,
) -> &mut Self
where
S: System<Input = (), Output = ()>,
IntoS: IntoSystem<Params, S>,
{
self.add_system_to_stage_internal(stage_name.into(), Box::new(system.system()));
self
}
pub fn add_boxed_system_to_stage(
&mut self,
stage_name: impl Into<Cow<'static, str>>,
system: Box<dyn System<Input = (), Output = ()>>,
) {
self.add_system_to_stage_internal(stage_name.into(), system);
}
fn add_system_to_stage_internal(
&mut self,
stage_name: Cow<'static, str>,
system: Box<dyn System<Input = (), Output = ()>>,
) {
let systems = self
.stages
.get_mut(&stage_name)
@ -117,15 +137,26 @@ impl Schedule {
systems.push(system);
self.generation += 1;
}
pub fn add_system_to_stage_front<S, Params, IntoS>(
&mut self,
stage_name: impl Into<Cow<'static, str>>,
system: IntoS,
) -> &mut Self
where
S: System<Input = (), Output = ()>,
IntoS: IntoSystem<Params, S>,
{
self.add_system_to_stage_front_internal(stage_name.into(), Box::new(system.system()));
self
}
pub fn add_system_to_stage_front(
fn add_system_to_stage_front_internal(
&mut self,
stage_name: impl Into<Cow<'static, str>>,
system: Box<dyn System>,
) -> &mut Self {
let stage_name = stage_name.into();
stage_name: Cow<'static, str>,
system: Box<dyn System<Input = (), Output = ()>>,
) {
let systems = self
.stages
.get_mut(&stage_name)
@ -141,7 +172,6 @@ impl Schedule {
systems.insert(0, system);
self.generation += 1;
self
}
pub fn run(&mut self, world: &mut World, resources: &mut Resources) {
@ -150,9 +180,11 @@ impl Schedule {
for system in stage_systems.iter_mut() {
system.update(world);
match system.thread_local_execution() {
ThreadLocalExecution::NextFlush => system.run(world, resources),
ThreadLocalExecution::NextFlush => {
system.run((), world, resources);
}
ThreadLocalExecution::Immediate => {
system.run(world, resources);
system.run((), world, resources);
// NOTE: when this is made parallel a full sync is required here
system.run_thread_local(world, resources);
}
@ -195,7 +227,10 @@ impl Schedule {
self.generation
}
pub fn run_on_systems(&mut self, mut func: impl FnMut(&mut dyn System)) {
pub fn run_on_systems(
&mut self,
mut func: impl FnMut(&mut dyn System<Input = (), Output = ()>),
) {
for stage_name in self.stage_order.iter() {
if let Some(stage_systems) = self.stages.get_mut(stage_name) {
for system in stage_systems.iter_mut() {

View file

@ -73,24 +73,23 @@ impl SystemState {
}
}
pub struct FuncSystem<F, Init, ThreadLocalFunc>
where
F: FnMut(&mut SystemState, &World, &Resources) + Send + Sync + 'static,
Init: FnMut(&mut SystemState, &World, &mut Resources) + Send + Sync + 'static,
ThreadLocalFunc: FnMut(&mut SystemState, &mut World, &mut Resources) + Send + Sync + 'static,
{
func: F,
thread_local_func: ThreadLocalFunc,
init_func: Init,
pub struct FuncSystem<Input, Return> {
func: Box<
dyn FnMut(Input, &mut SystemState, &World, &Resources) -> Option<Return>
+ Send
+ Sync
+ 'static,
>,
thread_local_func:
Box<dyn FnMut(&mut SystemState, &mut World, &mut Resources) + Send + Sync + 'static>,
init_func: Box<dyn FnMut(&mut SystemState, &World, &mut Resources) + Send + Sync + 'static>,
state: SystemState,
}
impl<F, Init, ThreadLocalFunc> System for FuncSystem<F, Init, ThreadLocalFunc>
where
F: FnMut(&mut SystemState, &World, &Resources) + Send + Sync + 'static,
Init: FnMut(&mut SystemState, &World, &mut Resources) + Send + Sync + 'static,
ThreadLocalFunc: FnMut(&mut SystemState, &mut World, &mut Resources) + Send + Sync + 'static,
{
impl<Input: 'static, Output: 'static> System for FuncSystem<Input, Output> {
type Input = Input;
type Output = Output;
fn name(&self) -> std::borrow::Cow<'static, str> {
self.state.name.clone()
}
@ -115,8 +114,13 @@ where
ThreadLocalExecution::NextFlush
}
fn run(&mut self, world: &World, resources: &Resources) {
(self.func)(&mut self.state, world, resources)
unsafe fn run_unsafe(
&mut self,
input: Input,
world: &World,
resources: &Resources,
) -> Option<Output> {
(self.func)(input, &mut self.state, world, resources)
}
fn run_thread_local(&mut self, world: &mut World, resources: &mut Resources) {
@ -133,20 +137,27 @@ where
}
}
pub trait IntoSystem<Params> {
fn system(self) -> Box<dyn System>;
pub trait IntoSystem<Params, SystemType: System> {
fn system(self) -> SystemType;
}
// Systems implicitly implement IntoSystem
impl<Sys: System> IntoSystem<(), Sys> for Sys {
fn system(self) -> Sys {
self
}
}
macro_rules! impl_into_system {
($($param: ident),*) => {
impl<Func, $($param: SystemParam),*> IntoSystem<($($param,)*)> for Func
where Func: FnMut($($param),*) + Send + Sync + 'static,
impl<Func, Input, Return, $($param: SystemParam<Input>),*> IntoSystem<($($param,)*), FuncSystem<Input, Return>> for Func
where Func: FnMut($($param),*) -> Return + Send + Sync + 'static, Return: 'static, Input: 'static
{
#[allow(unused_variables)]
#[allow(unused_unsafe)]
#[allow(non_snake_case)]
fn system(mut self) -> Box<dyn System> {
Box::new(FuncSystem {
fn system(mut self) -> FuncSystem<Input, Return> {
FuncSystem {
state: SystemState {
name: std::any::type_name::<Self>().into(),
archetype_component_access: TypeAccess::default(),
@ -161,28 +172,30 @@ macro_rules! impl_into_system {
query_type_names: Vec::new(),
current_query_index: 0,
},
func: move |state, world, resources| {
func: Box::new(move |input, state, world, resources| {
state.reset_indices();
let mut input = Some(input);
unsafe {
if let Some(($($param,)*)) = <($($param,)*)>::get_param(state, world, resources) {
self($($param),*);
if let Some(($($param,)*)) = <($($param,)*)>::get_param(&mut input, state, world, resources) {
Some(self($($param),*))
} else {
None
}
}
},
thread_local_func: |state, world, resources| {
}),
thread_local_func: Box::new(|state, world, resources| {
state.commands.apply(world, resources);
if let Some(ref commands) = state.arc_commands {
let mut commands = commands.lock();
commands.apply(world, resources);
}
},
init_func: |state, world, resources| {
}),
init_func: Box::new(|state, world, resources| {
$($param::init(state, world, resources);)*
},
})
}),
}
}
}
};
}
@ -273,7 +286,7 @@ mod tests {
world.spawn((A, C));
world.spawn((A, D));
run_system(&mut world, &mut resources, query_system.system());
run_system(&mut world, &mut resources, query_system);
assert!(*resources.get::<bool>().unwrap(), "system ran");
}
@ -304,7 +317,7 @@ mod tests {
resources.insert(false);
world.spawn((A, B));
run_system(&mut world, &mut resources, query_system.system());
run_system(&mut world, &mut resources, query_system);
assert!(*resources.get::<bool>().unwrap(), "system ran");
}
@ -324,7 +337,7 @@ mod tests {
let mut schedule = Schedule::default();
schedule.add_stage("update");
schedule.add_system_to_stage("update", incr_e_on_flip.system());
schedule.add_system_to_stage("update", incr_e_on_flip);
schedule.initialize(&mut world, &mut resources);
schedule.run(&mut world, &mut resources);
@ -357,7 +370,7 @@ mod tests {
let mut schedule = Schedule::default();
schedule.add_stage("update");
schedule.add_system_to_stage("update", incr_e_on_flip.system());
schedule.add_system_to_stage("update", incr_e_on_flip);
schedule.initialize(&mut world, &mut resources);
schedule.run(&mut world, &mut resources);
@ -387,7 +400,7 @@ mod tests {
let mut resources = Resources::default();
world.spawn((A,));
run_system(&mut world, &mut resources, sys.system());
run_system(&mut world, &mut resources, sys);
}
#[test]
@ -399,7 +412,7 @@ mod tests {
let mut resources = Resources::default();
world.spawn((A,));
run_system(&mut world, &mut resources, sys.system());
run_system(&mut world, &mut resources, sys);
}
#[test]
@ -410,7 +423,7 @@ mod tests {
let mut resources = Resources::default();
world.spawn((A,));
run_system(&mut world, &mut resources, sys.system());
run_system(&mut world, &mut resources, sys);
}
#[test]
@ -422,7 +435,7 @@ mod tests {
let mut resources = Resources::default();
world.spawn((A,));
run_system(&mut world, &mut resources, sys.system());
run_system(&mut world, &mut resources, sys);
}
#[test]
@ -433,10 +446,18 @@ mod tests {
let mut world = World::default();
let mut resources = Resources::default();
world.spawn((A,));
run_system(&mut world, &mut resources, sys.system());
run_system(&mut world, &mut resources, sys);
}
fn run_system(world: &mut World, resources: &mut Resources, system: Box<dyn System>) {
fn run_system<
Params,
SystemType: System<Input = (), Output = ()>,
Sys: IntoSystem<Params, SystemType>,
>(
world: &mut World,
resources: &mut Resources,
system: Sys,
) {
let mut schedule = Schedule::default();
schedule.add_stage("update");
schedule.add_system_to_stage("update", system);
@ -450,7 +471,13 @@ mod tests {
_buffer: Vec<u8>,
}
fn test_for_conflicting_resources(sys: Box<dyn System>) {
fn test_for_conflicting_resources<
Params,
SystemType: System<Input = (), Output = ()>,
Sys: IntoSystem<Params, SystemType>,
>(
sys: Sys,
) {
let mut world = World::default();
let mut resources = Resources::default();
resources.insert(BufferRes::default());
@ -463,21 +490,21 @@ mod tests {
#[should_panic]
fn conflicting_system_resources() {
fn sys(_: ResMut<BufferRes>, _: Res<BufferRes>) {}
test_for_conflicting_resources(sys.system())
test_for_conflicting_resources(sys)
}
#[test]
#[should_panic]
fn conflicting_system_resources_reverse_order() {
fn sys(_: Res<BufferRes>, _: ResMut<BufferRes>) {}
test_for_conflicting_resources(sys.system())
test_for_conflicting_resources(sys)
}
#[test]
#[should_panic]
fn conflicting_system_resources_multiple_mutable() {
fn sys(_: ResMut<BufferRes>, _: ResMut<BufferRes>) {}
test_for_conflicting_resources(sys.system())
test_for_conflicting_resources(sys)
}
#[test]
@ -485,19 +512,19 @@ mod tests {
fn conflicting_changed_and_mutable_resource() {
// A tempting pattern, but unsound if allowed.
fn sys(_: ResMut<BufferRes>, _: ChangedRes<BufferRes>) {}
test_for_conflicting_resources(sys.system())
test_for_conflicting_resources(sys)
}
#[test]
#[should_panic]
fn conflicting_system_local_resources() {
fn sys(_: Local<BufferRes>, _: Local<BufferRes>) {}
test_for_conflicting_resources(sys.system())
test_for_conflicting_resources(sys)
}
#[test]
fn nonconflicting_system_resources() {
fn sys(_: Local<BufferRes>, _: ResMut<BufferRes>, _: Local<A>, _: ResMut<A>) {}
test_for_conflicting_resources(sys.system())
test_for_conflicting_resources(sys)
}
}

View file

@ -2,26 +2,22 @@ pub use super::Query;
use crate::{
resource::Resources,
system::{System, SystemId, ThreadLocalExecution},
ArchetypeComponent, TypeAccess, World,
ArchetypeComponent, IntoSystem, TypeAccess, World,
};
use std::{any::TypeId, borrow::Cow};
#[derive(Debug)]
pub(crate) struct ThreadLocalSystemFn<Func>
where
Func: FnMut(&mut World, &mut Resources) + Send + Sync,
{
pub func: Func,
pub struct ThreadLocalSystemFn {
pub func: Box<dyn FnMut(&mut World, &mut Resources) + Send + Sync + 'static>,
pub resource_access: TypeAccess<TypeId>,
pub archetype_component_access: TypeAccess<ArchetypeComponent>,
pub name: Cow<'static, str>,
pub id: SystemId,
}
impl<Func> System for ThreadLocalSystemFn<Func>
where
Func: FnMut(&mut World, &mut Resources) + Send + Sync,
{
impl System for ThreadLocalSystemFn {
type Input = ();
type Output = ();
fn name(&self) -> Cow<'static, str> {
self.name.clone()
}
@ -40,7 +36,14 @@ where
ThreadLocalExecution::Immediate
}
fn run(&mut self, _world: &World, _resources: &Resources) {}
unsafe fn run_unsafe(
&mut self,
_input: (),
_world: &World,
_resources: &Resources,
) -> Option<()> {
Some(())
}
fn run_thread_local(&mut self, world: &mut World, resources: &mut Resources) {
(self.func)(world, resources);
@ -57,22 +60,17 @@ where
}
}
/// Converts `Self` into a thread local system
pub trait IntoThreadLocalSystem {
fn thread_local_system(self) -> Box<dyn System>;
}
impl<F> IntoThreadLocalSystem for F
impl<F> IntoSystem<(&mut World, &mut Resources), ThreadLocalSystemFn> for F
where
F: FnMut(&mut World, &mut Resources) + Send + Sync + 'static,
{
fn thread_local_system(mut self) -> Box<dyn System> {
Box::new(ThreadLocalSystemFn {
func: move |world, resources| (self)(world, resources),
fn system(mut self) -> ThreadLocalSystemFn {
ThreadLocalSystemFn {
func: Box::new(move |world, resources| (self)(world, resources)),
name: core::any::type_name::<F>().into(),
id: SystemId::new(),
resource_access: TypeAccess::default(),
archetype_component_access: TypeAccess::default(),
})
}
}
}

View file

@ -4,6 +4,7 @@ mod into_thread_local;
mod query;
#[allow(clippy::module_inception)]
mod system;
mod system_chaining;
mod system_param;
pub use commands::*;
@ -11,4 +12,5 @@ pub use into_system::*;
pub use into_thread_local::*;
pub use query::*;
pub use system::*;
pub use system_chaining::*;
pub use system_param::*;

View file

@ -19,7 +19,9 @@ impl SystemId {
}
/// An ECS system that can be added to a [Schedule](crate::Schedule)
pub trait System: Send + Sync {
pub trait System: Send + Sync + 'static {
type Input;
type Output;
fn name(&self) -> Cow<'static, str>;
fn id(&self) -> SystemId;
fn is_initialized(&self) -> bool;
@ -27,7 +29,25 @@ pub trait System: Send + Sync {
fn archetype_component_access(&self) -> &TypeAccess<ArchetypeComponent>;
fn resource_access(&self) -> &TypeAccess<TypeId>;
fn thread_local_execution(&self) -> ThreadLocalExecution;
fn run(&mut self, world: &World, resources: &Resources);
/// # Safety
/// This might access World and Resources in an unsafe manner. This should only be called in one of the following contexts:
/// 1. This system is the only system running on the given World and Resources across all threads
/// 2. This system only runs in parallel with other systems that do not conflict with the `archetype_component_access()` or `resource_access()`
unsafe fn run_unsafe(
&mut self,
input: Self::Input,
world: &World,
resources: &Resources,
) -> Option<Self::Output>;
fn run(
&mut self,
input: Self::Input,
world: &mut World,
resources: &mut Resources,
) -> Option<Self::Output> {
// SAFE: world and resources are exclusively borrowed
unsafe { self.run_unsafe(input, world, resources) }
}
fn run_thread_local(&mut self, world: &mut World, resources: &mut Resources);
fn initialize(&mut self, _world: &mut World, _resources: &mut Resources) {}
}

View file

@ -0,0 +1,103 @@
use crate::{
ArchetypeComponent, IntoSystem, Resources, System, SystemId, ThreadLocalExecution, TypeAccess,
World,
};
use std::{any::TypeId, borrow::Cow};
pub struct ChainSystem<SystemA, SystemB> {
system_a: SystemA,
system_b: SystemB,
name: Cow<'static, str>,
id: SystemId,
pub(crate) archetype_component_access: TypeAccess<ArchetypeComponent>,
pub(crate) resource_access: TypeAccess<TypeId>,
}
impl<SystemA: System, SystemB: System<Input = SystemA::Output>> System
for ChainSystem<SystemA, SystemB>
{
type Input = SystemA::Input;
type Output = SystemB::Output;
fn name(&self) -> Cow<'static, str> {
self.name.clone()
}
fn id(&self) -> SystemId {
self.id
}
fn is_initialized(&self) -> bool {
self.system_a.is_initialized() && self.system_b.is_initialized()
}
fn update(&mut self, world: &World) {
self.archetype_component_access.clear();
self.resource_access.clear();
self.system_a.update(world);
self.system_b.update(world);
self.archetype_component_access
.union(self.system_a.archetype_component_access());
self.resource_access.union(self.system_b.resource_access());
}
fn archetype_component_access(&self) -> &TypeAccess<ArchetypeComponent> {
&self.archetype_component_access
}
fn resource_access(&self) -> &TypeAccess<TypeId> {
&self.resource_access
}
fn thread_local_execution(&self) -> ThreadLocalExecution {
ThreadLocalExecution::NextFlush
}
unsafe fn run_unsafe(
&mut self,
input: Self::Input,
world: &World,
resources: &Resources,
) -> Option<Self::Output> {
let out = self.system_a.run_unsafe(input, world, resources).unwrap();
self.system_b.run_unsafe(out, world, resources)
}
fn run_thread_local(&mut self, world: &mut World, resources: &mut Resources) {
self.system_a.run_thread_local(world, resources);
self.system_b.run_thread_local(world, resources);
}
}
pub trait IntoChainSystem<AParams, BParams, IntoB, SystemA, SystemB>:
IntoSystem<AParams, SystemA> + Sized
where
IntoB: IntoSystem<BParams, SystemB>,
SystemA: System,
SystemB: System<Input = SystemA::Output>,
{
fn chain(self, system: IntoB) -> ChainSystem<SystemA, SystemB>;
}
impl<AParams, BParams, IntoA, IntoB, SystemA, SystemB>
IntoChainSystem<AParams, BParams, IntoB, SystemA, SystemB> for IntoA
where
SystemA: System,
SystemB: System<Input = SystemA::Output>,
IntoA: IntoSystem<AParams, SystemA>,
IntoB: IntoSystem<BParams, SystemB>,
{
fn chain(self, system: IntoB) -> ChainSystem<SystemA, SystemB> {
let system_a = self.system();
let system_b = system.system();
ChainSystem {
name: Cow::Owned(format!("Chain({}, {})", system_a.name(), system_b.name())),
system_a,
system_b,
archetype_component_access: Default::default(),
resource_access: Default::default(),
id: SystemId::new(),
}
}
}

View file

@ -6,21 +6,39 @@ use crate::{
use parking_lot::Mutex;
use std::{any::TypeId, sync::Arc};
pub trait SystemParam: Sized {
pub struct In<Input>(pub Input);
impl<Input> SystemParam<Input> for In<Input> {
#[inline]
unsafe fn get_param(
input: &mut Option<Input>,
_system_state: &mut SystemState,
_world: &World,
_resources: &Resources,
) -> Option<Self> {
Some(In(input.take().unwrap()))
}
fn init(_system_state: &mut SystemState, _world: &World, _resources: &mut Resources) {}
}
pub trait SystemParam<Input>: Sized {
fn init(system_state: &mut SystemState, world: &World, resources: &mut Resources);
/// # Safety
/// This call might access any of the input parameters in an unsafe way. Make sure the data access is safe in
/// the context of the system scheduler
unsafe fn get_param(
input: &mut Option<Input>,
system_state: &mut SystemState,
world: &World,
resources: &Resources,
) -> Option<Self>;
}
impl<'a, Q: WorldQuery, F: QueryFilter> SystemParam for Query<'a, Q, F> {
impl<'a, Q: WorldQuery, F: QueryFilter, Input> SystemParam<Input> for Query<'a, Q, F> {
#[inline]
unsafe fn get_param(
_input: &mut Option<Input>,
system_state: &mut SystemState,
world: &World,
_resources: &Resources,
@ -45,9 +63,10 @@ impl<'a, Q: WorldQuery, F: QueryFilter> SystemParam for Query<'a, Q, F> {
}
}
impl<T: QueryTuple> SystemParam for QuerySet<T> {
impl<T: QueryTuple, Input> SystemParam<Input> for QuerySet<T> {
#[inline]
unsafe fn get_param(
_input: &mut Option<Input>,
system_state: &mut SystemState,
world: &World,
_resources: &Resources,
@ -71,7 +90,7 @@ impl<T: QueryTuple> SystemParam for QuerySet<T> {
}
}
impl<'a> SystemParam for &'a mut Commands {
impl<'a, Input> SystemParam<Input> for &'a mut Commands {
fn init(system_state: &mut SystemState, world: &World, _resources: &mut Resources) {
system_state
.commands
@ -80,6 +99,7 @@ impl<'a> SystemParam for &'a mut Commands {
#[inline]
unsafe fn get_param(
_input: &mut Option<Input>,
system_state: &mut SystemState,
_world: &World,
_resources: &Resources,
@ -89,7 +109,7 @@ impl<'a> SystemParam for &'a mut Commands {
}
}
impl SystemParam for Arc<Mutex<Commands>> {
impl<Input> SystemParam<Input> for Arc<Mutex<Commands>> {
fn init(system_state: &mut SystemState, world: &World, _resources: &mut Resources) {
system_state.arc_commands.get_or_insert_with(|| {
let mut commands = Commands::default();
@ -100,6 +120,7 @@ impl SystemParam for Arc<Mutex<Commands>> {
#[inline]
unsafe fn get_param(
_input: &mut Option<Input>,
system_state: &mut SystemState,
_world: &World,
_resources: &Resources,
@ -108,7 +129,7 @@ impl SystemParam for Arc<Mutex<Commands>> {
}
}
impl<'a, T: Resource> SystemParam for Res<'a, T> {
impl<'a, T: Resource, Input> SystemParam<Input> for Res<'a, T> {
fn init(system_state: &mut SystemState, _world: &World, _resources: &mut Resources) {
if system_state.resource_access.is_write(&TypeId::of::<T>()) {
panic!(
@ -123,6 +144,7 @@ impl<'a, T: Resource> SystemParam for Res<'a, T> {
#[inline]
unsafe fn get_param(
_input: &mut Option<Input>,
_system_state: &mut SystemState,
_world: &World,
resources: &Resources,
@ -133,7 +155,7 @@ impl<'a, T: Resource> SystemParam for Res<'a, T> {
}
}
impl<'a, T: Resource> SystemParam for ResMut<'a, T> {
impl<'a, T: Resource, Input> SystemParam<Input> for ResMut<'a, T> {
fn init(system_state: &mut SystemState, _world: &World, _resources: &mut Resources) {
// If a system already has access to the resource in another parameter, then we fail early.
// e.g. `fn(Res<Foo>, ResMut<Foo>)` or `fn(ResMut<Foo>, ResMut<Foo>)` must not be allowed.
@ -153,6 +175,7 @@ impl<'a, T: Resource> SystemParam for ResMut<'a, T> {
#[inline]
unsafe fn get_param(
_input: &mut Option<Input>,
_system_state: &mut SystemState,
_world: &World,
resources: &Resources,
@ -163,7 +186,7 @@ impl<'a, T: Resource> SystemParam for ResMut<'a, T> {
}
}
impl<'a, T: Resource> SystemParam for ChangedRes<'a, T> {
impl<'a, T: Resource, Input> SystemParam<Input> for ChangedRes<'a, T> {
fn init(system_state: &mut SystemState, _world: &World, _resources: &mut Resources) {
if system_state.resource_access.is_write(&TypeId::of::<T>()) {
panic!(
@ -178,6 +201,7 @@ impl<'a, T: Resource> SystemParam for ChangedRes<'a, T> {
#[inline]
unsafe fn get_param(
_input: &mut Option<Input>,
_system_state: &mut SystemState,
_world: &World,
resources: &Resources,
@ -192,7 +216,7 @@ impl<'a, T: Resource> SystemParam for ChangedRes<'a, T> {
}
}
impl<'a, T: Resource + FromResources> SystemParam for Local<'a, T> {
impl<'a, T: Resource + FromResources, Input> SystemParam<Input> for Local<'a, T> {
fn init(system_state: &mut SystemState, _world: &World, resources: &mut Resources) {
if system_state
.local_resource_access
@ -220,6 +244,7 @@ impl<'a, T: Resource + FromResources> SystemParam for Local<'a, T> {
#[inline]
unsafe fn get_param(
_input: &mut Option<Input>,
system_state: &mut SystemState,
_world: &World,
resources: &Resources,
@ -231,38 +256,40 @@ impl<'a, T: Resource + FromResources> SystemParam for Local<'a, T> {
macro_rules! impl_system_param_tuple {
($($param: ident),*) => {
#[allow(unused_variables)]
impl<$($param: SystemParam),*> SystemParam for ($($param,)*) {
impl<Input, $($param: SystemParam<Input>),*> SystemParam<Input> for ($($param,)*) {
fn init(system_state: &mut SystemState, world: &World, resources: &mut Resources) {
$($param::init(system_state, world, resources);)*
}
#[inline]
unsafe fn get_param(
input: &mut Option<Input>,
system_state: &mut SystemState,
world: &World,
resources: &Resources,
) -> Option<Self> {
Some(($($param::get_param(system_state, world, resources)?,)*))
Some(($($param::get_param(input, system_state, world, resources)?,)*))
}
}
#[allow(unused_variables)]
#[allow(unused_mut)]
#[allow(non_snake_case)]
impl<$($param: SystemParam),*> SystemParam for Or<($(Option<$param>,)*)> {
impl<Input, $($param: SystemParam<Input>),*> SystemParam<Input> for Or<($(Option<$param>,)*)> {
fn init(system_state: &mut SystemState, world: &World, resources: &mut Resources) {
$($param::init(system_state, world, resources);)*
}
#[inline]
unsafe fn get_param(
input: &mut Option<Input>,
system_state: &mut SystemState,
world: &World,
resources: &Resources,
) -> Option<Self> {
let mut has_some = false;
$(
let $param = $param::get_param(system_state, world, resources);
let $param = $param::get_param(input, system_state, world, resources);
if $param.is_some() {
has_some = true;
}

View file

@ -2,7 +2,6 @@ mod converter;
mod gilrs_system;
use bevy_app::{prelude::*, startup_stage::PRE_STARTUP};
use bevy_ecs::prelude::*;
use bevy_utils::tracing::error;
use gilrs::GilrsBuilder;
use gilrs_system::{gilrs_event_startup_system, gilrs_event_system};
@ -19,14 +18,8 @@ impl Plugin for GilrsPlugin {
{
Ok(gilrs) => {
app.add_thread_local_resource(gilrs)
.add_startup_system_to_stage(
PRE_STARTUP,
gilrs_event_startup_system.thread_local_system(),
)
.add_system_to_stage(
stage::PRE_EVENT,
gilrs_event_system.thread_local_system(),
);
.add_startup_system_to_stage(PRE_STARTUP, gilrs_event_startup_system)
.add_system_to_stage(stage::PRE_EVENT, gilrs_event_system);
}
Err(err) => error!("Failed to start Gilrs. {}", err),
}

View file

@ -28,7 +28,6 @@ use mouse::{mouse_button_input_system, MouseButton, MouseButtonInput, MouseMotio
use touch::{touch_screen_input_system, TouchInput, Touches};
use bevy_app::startup_stage::STARTUP;
use bevy_ecs::IntoSystem;
use gamepad::{
gamepad_event_system, GamepadAxis, GamepadButton, GamepadEvent, GamepadEventRaw,
GamepadSettings,
@ -45,20 +44,20 @@ impl Plugin for InputPlugin {
.add_event::<MouseMotion>()
.add_event::<MouseWheel>()
.init_resource::<Input<KeyCode>>()
.add_system_to_stage(bevy_app::stage::EVENT, keyboard_input_system.system())
.add_system_to_stage(bevy_app::stage::EVENT, keyboard_input_system)
.init_resource::<Input<MouseButton>>()
.add_system_to_stage(bevy_app::stage::EVENT, mouse_button_input_system.system())
.add_system_to_stage(bevy_app::stage::EVENT, mouse_button_input_system)
.add_event::<GamepadEvent>()
.add_event::<GamepadEventRaw>()
.init_resource::<GamepadSettings>()
.init_resource::<Input<GamepadButton>>()
.init_resource::<Axis<GamepadAxis>>()
.init_resource::<Axis<GamepadButton>>()
.add_system_to_stage(bevy_app::stage::EVENT, gamepad_event_system.system())
.add_startup_system_to_stage(STARTUP, gamepad_event_system.system())
.add_system_to_stage(bevy_app::stage::EVENT, gamepad_event_system)
.add_startup_system_to_stage(STARTUP, gamepad_event_system)
.add_event::<TouchInput>()
.init_resource::<Touches>()
.add_system_to_stage(bevy_app::stage::EVENT, touch_screen_input_system.system());
.add_system_to_stage(bevy_app::stage::EVENT, touch_screen_input_system);
}
}

View file

@ -14,7 +14,6 @@ pub mod prelude {
use bevy_app::prelude::*;
use bevy_asset::{AddAsset, Assets, Handle};
use bevy_ecs::IntoSystem;
use bevy_render::{prelude::Color, render_graph::RenderGraph, shader};
use bevy_type_registry::RegisterType;
use light::Light;
@ -31,7 +30,7 @@ impl Plugin for PbrPlugin {
.register_component::<Light>()
.add_system_to_stage(
stage::POST_UPDATE,
shader::asset_shader_defs_system::<StandardMaterial>.system(),
shader::asset_shader_defs_system::<StandardMaterial>,
)
.init_resource::<AmbientLight>();
let resources = app.resources();

View file

@ -51,7 +51,7 @@ struct LightCount {
unsafe impl Byteable for LightCount {}
impl SystemNode for LightsNode {
fn get_system(&self, commands: &mut Commands) -> Box<dyn System> {
fn get_system(&self, commands: &mut Commands) -> Box<dyn System<Input = (), Output = ()>> {
let system = lights_node_system.system();
commands.insert_local_resource(
system.id(),
@ -62,7 +62,7 @@ impl SystemNode for LightsNode {
staging_buffer: None,
},
);
system
Box::new(system)
}
}

View file

@ -32,7 +32,6 @@ use crate::prelude::*;
use base::{MainPass, Msaa};
use bevy_app::prelude::*;
use bevy_asset::AddAsset;
use bevy_ecs::{IntoSystem, IntoThreadLocalSystem};
use camera::{
ActiveCameras, Camera, OrthographicProjection, PerspectiveProjection, VisibleEntities,
};
@ -121,45 +120,30 @@ impl Plugin for RenderPlugin {
.init_resource::<TextureResourceSystemState>()
.init_resource::<AssetRenderResourceBindings>()
.init_resource::<ActiveCameras>()
.add_system_to_stage(bevy_app::stage::PRE_UPDATE, draw::clear_draw_system)
.add_system_to_stage(bevy_app::stage::POST_UPDATE, camera::active_cameras_system)
.add_system_to_stage(
bevy_app::stage::PRE_UPDATE,
draw::clear_draw_system.system(),
bevy_app::stage::POST_UPDATE,
camera::camera_system::<OrthographicProjection>,
)
.add_system_to_stage(
bevy_app::stage::POST_UPDATE,
camera::active_cameras_system.system(),
)
.add_system_to_stage(
bevy_app::stage::POST_UPDATE,
camera::camera_system::<OrthographicProjection>.system(),
)
.add_system_to_stage(
bevy_app::stage::POST_UPDATE,
camera::camera_system::<PerspectiveProjection>.system(),
camera::camera_system::<PerspectiveProjection>,
)
// registration order matters here. this must come after all camera_system::<T> systems
.add_system_to_stage(
bevy_app::stage::POST_UPDATE,
camera::visible_entities_system.system(),
camera::visible_entities_system,
)
// TODO: turn these "resource systems" into graph nodes and remove the RENDER_RESOURCE stage
.add_system_to_stage(
stage::RENDER_RESOURCE,
mesh::mesh_resource_provider_system.system(),
)
.add_system_to_stage(
stage::RENDER_RESOURCE,
Texture::texture_resource_system.system(),
)
.add_system_to_stage(stage::RENDER_RESOURCE, mesh::mesh_resource_provider_system)
.add_system_to_stage(stage::RENDER_RESOURCE, Texture::texture_resource_system)
.add_system_to_stage(
stage::RENDER_GRAPH_SYSTEMS,
render_graph::render_graph_schedule_executor_system.thread_local_system(),
render_graph::render_graph_schedule_executor_system,
)
.add_system_to_stage(stage::DRAW, pipeline::draw_render_pipelines_system.system())
.add_system_to_stage(
stage::POST_RENDER,
shader::clear_shader_defs_system.system(),
);
.add_system_to_stage(stage::DRAW, pipeline::draw_render_pipelines_system)
.add_system_to_stage(stage::POST_RENDER, shader::clear_shader_defs_system);
if app.resources().get::<Msaa>().is_none() {
app.init_resource::<Msaa>();

View file

@ -43,7 +43,7 @@ impl RenderGraph {
self.system_node_schedule
.as_mut()
.unwrap()
.add_system_to_stage("update", node.get_system(&mut self.commands));
.add_boxed_system_to_stage("update", node.get_system(&mut self.commands));
self.add_node(name, node)
}

View file

@ -37,7 +37,7 @@ pub trait Node: Downcast + Send + Sync + 'static {
impl_downcast!(Node);
pub trait SystemNode: Node {
fn get_system(&self, commands: &mut Commands) -> Box<dyn System>;
fn get_system(&self, commands: &mut Commands) -> Box<dyn System<Input = (), Output = ()>>;
}
#[derive(Debug)]

View file

@ -44,7 +44,7 @@ impl Node for CameraNode {
}
impl SystemNode for CameraNode {
fn get_system(&self, commands: &mut Commands) -> Box<dyn System> {
fn get_system(&self, commands: &mut Commands) -> Box<dyn System<Input = (), Output = ()>> {
let system = camera_node_system.system();
commands.insert_local_resource(
system.id(),
@ -55,7 +55,7 @@ impl SystemNode for CameraNode {
staging_buffer: None,
},
);
system
Box::new(system)
}
}

View file

@ -387,7 +387,7 @@ impl<T> SystemNode for RenderResourcesNode<T>
where
T: renderer::RenderResources,
{
fn get_system(&self, commands: &mut Commands) -> Box<dyn System> {
fn get_system(&self, commands: &mut Commands) -> Box<dyn System<Input = (), Output = ()>> {
let system = render_resources_node_system::<T>.system();
commands.insert_local_resource(
system.id(),
@ -398,7 +398,7 @@ where
},
);
system
Box::new(system)
}
}
@ -527,7 +527,7 @@ impl<T> SystemNode for AssetRenderResourcesNode<T>
where
T: renderer::RenderResources + Asset,
{
fn get_system(&self, commands: &mut Commands) -> Box<dyn System> {
fn get_system(&self, commands: &mut Commands) -> Box<dyn System<Input = (), Output = ()>> {
let system = asset_render_resources_node_system::<T>.system();
commands.insert_local_resource(
system.id(),
@ -538,7 +538,7 @@ where
},
);
system
Box::new(system)
}
}

View file

@ -17,7 +17,6 @@ pub mod prelude {
use bevy_app::prelude::*;
use bevy_asset::AddAsset;
use bevy_ecs::IntoThreadLocalSystem;
#[derive(Default)]
pub struct ScenePlugin;
@ -31,6 +30,6 @@ impl Plugin for ScenePlugin {
.init_asset_loader::<SceneLoader>()
.init_resource::<SceneSpawner>()
.add_stage_after(stage::EVENT, SCENE_STAGE)
.add_system_to_stage(SCENE_STAGE, scene_spawner_system.thread_local_system());
.add_system_to_stage(SCENE_STAGE, scene_spawner_system);
}
}

View file

@ -26,7 +26,6 @@ pub mod prelude {
use bevy_app::prelude::*;
use bevy_asset::{AddAsset, Assets, Handle};
use bevy_ecs::IntoSystem;
use bevy_math::Vec2;
use bevy_render::{
mesh::{shape, Mesh},
@ -45,10 +44,10 @@ impl Plugin for SpritePlugin {
fn build(&self, app: &mut AppBuilder) {
app.add_asset::<ColorMaterial>()
.add_asset::<TextureAtlas>()
.add_system_to_stage(stage::POST_UPDATE, sprite_system.system())
.add_system_to_stage(stage::POST_UPDATE, sprite_system)
.add_system_to_stage(
stage::POST_UPDATE,
asset_shader_defs_system::<ColorMaterial>.system(),
asset_shader_defs_system::<ColorMaterial>,
);
let resources = app.resources_mut();

View file

@ -1,5 +1,5 @@
use crate::components::*;
use bevy_ecs::{Changed, Commands, Entity, IntoSystem, Query, System, Without};
use bevy_ecs::{Changed, Commands, Entity, Query, Without};
use bevy_utils::HashMap;
use smallvec::SmallVec;
@ -64,15 +64,10 @@ pub fn parent_update_system(
commands.insert_one(*k, Children::with(v));
});
}
pub fn hierarchy_maintenance_systems() -> Vec<Box<dyn System>> {
vec![parent_update_system.system()]
}
#[cfg(test)]
mod test {
use super::*;
use crate::{hierarchy::BuildChildren, transform_systems};
use crate::{hierarchy::BuildChildren, transform_propagate_system::transform_propagate_system};
use bevy_ecs::{Resources, Schedule, World};
use bevy_math::Vec3;
@ -83,9 +78,8 @@ mod test {
let mut schedule = Schedule::default();
schedule.add_stage("update");
for system in transform_systems() {
schedule.add_system_to_stage("update", system);
}
schedule.add_system_to_stage("update", parent_update_system);
schedule.add_system_to_stage("update", transform_propagate_system);
// Add parent entities
let mut commands = Commands::default();

View file

@ -7,18 +7,8 @@ pub mod prelude {
}
use bevy_app::prelude::*;
use bevy_ecs::prelude::*;
use bevy_type_registry::RegisterType;
use prelude::{Children, GlobalTransform, Parent, Transform};
pub(crate) fn transform_systems() -> Vec<Box<dyn System>> {
let mut systems = Vec::with_capacity(5);
systems.append(&mut hierarchy::hierarchy_maintenance_systems());
systems.push(transform_propagate_system::transform_propagate_system.system());
systems
}
use prelude::{parent_update_system, Children, GlobalTransform, Parent, Transform};
#[derive(Default)]
pub struct TransformPlugin;
@ -30,7 +20,12 @@ impl Plugin for TransformPlugin {
.register_component::<Transform>()
.register_component::<GlobalTransform>()
// add transform systems to startup so the first update is "correct"
.add_startup_systems(transform_systems())
.add_systems_to_stage(stage::POST_UPDATE, transform_systems());
.add_startup_system(parent_update_system)
.add_startup_system(transform_propagate_system::transform_propagate_system)
.add_system_to_stage(stage::POST_UPDATE, parent_update_system)
.add_system_to_stage(
stage::POST_UPDATE,
transform_propagate_system::transform_propagate_system,
);
}
}

View file

@ -50,7 +50,7 @@ fn propagate_recursive(
#[cfg(test)]
mod test {
use super::*;
use crate::{hierarchy::BuildChildren, transform_systems};
use crate::hierarchy::{parent_update_system, BuildChildren};
use bevy_ecs::{Resources, Schedule, World};
use bevy_math::Vec3;
@ -61,9 +61,8 @@ mod test {
let mut schedule = Schedule::default();
schedule.add_stage("update");
for system in transform_systems() {
schedule.add_system_to_stage("update", system);
}
schedule.add_system_to_stage("update", parent_update_system);
schedule.add_system_to_stage("update", transform_propagate_system);
// Root entity
let parent = world.spawn((
@ -111,9 +110,8 @@ mod test {
let mut schedule = Schedule::default();
schedule.add_stage("update");
for system in transform_systems() {
schedule.add_system_to_stage("update", system);
}
schedule.add_system_to_stage("update", parent_update_system);
schedule.add_system_to_stage("update", transform_propagate_system);
// Root entity
let mut commands = Commands::default();

View file

@ -25,7 +25,6 @@ pub mod prelude {
}
use bevy_app::prelude::*;
use bevy_ecs::IntoSystem;
use bevy_render::render_graph::RenderGraph;
use update::ui_z_system;
@ -40,13 +39,13 @@ impl Plugin for UiPlugin {
fn build(&self, app: &mut AppBuilder) {
app.init_resource::<FlexSurface>()
.add_stage_before(bevy_app::stage::POST_UPDATE, stage::UI)
.add_system_to_stage(bevy_app::stage::PRE_UPDATE, ui_focus_system.system())
.add_system_to_stage(bevy_app::stage::PRE_UPDATE, ui_focus_system)
// add these stages to front because these must run before transform update systems
.add_system_to_stage(stage::UI, widget::text_system.system())
.add_system_to_stage(stage::UI, widget::image_node_system.system())
.add_system_to_stage(stage::UI, ui_z_system.system())
.add_system_to_stage(stage::UI, flex_node_system.system())
.add_system_to_stage(bevy_render::stage::DRAW, widget::draw_text_system.system());
.add_system_to_stage(stage::UI, widget::text_system)
.add_system_to_stage(stage::UI, widget::image_node_system)
.add_system_to_stage(stage::UI, ui_z_system)
.add_system_to_stage(stage::UI, flex_node_system)
.add_system_to_stage(bevy_render::stage::DRAW, widget::draw_text_system);
let resources = app.resources();
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();

View file

@ -1,7 +1,7 @@
use crate::renderer::WgpuRenderResourceContext;
use bevy_app::prelude::*;
use bevy_diagnostic::{Diagnostic, DiagnosticId, Diagnostics};
use bevy_ecs::{IntoSystem, Res, ResMut};
use bevy_ecs::{Res, ResMut};
use bevy_render::renderer::RenderResourceContext;
#[derive(Default)]
@ -9,8 +9,8 @@ pub struct WgpuResourceDiagnosticsPlugin;
impl Plugin for WgpuResourceDiagnosticsPlugin {
fn build(&self, app: &mut AppBuilder) {
app.add_startup_system(Self::setup_system.system())
.add_system(Self::diagnostic_system.system());
app.add_startup_system(Self::setup_system)
.add_system(Self::diagnostic_system);
}
}

View file

@ -11,7 +11,7 @@ pub use wgpu_renderer::*;
pub use wgpu_resources::*;
use bevy_app::prelude::*;
use bevy_ecs::{IntoSystem, IntoThreadLocalSystem, Resources, World};
use bevy_ecs::{Resources, World};
use bevy_render::renderer::{free_shared_buffers_system, RenderResourceContext, SharedBuffers};
use renderer::WgpuRenderResourceContext;
@ -21,14 +21,8 @@ pub struct WgpuPlugin;
impl Plugin for WgpuPlugin {
fn build(&self, app: &mut AppBuilder) {
let render_system = get_wgpu_render_system(app.resources_mut());
app.add_system_to_stage(
bevy_render::stage::RENDER,
render_system.thread_local_system(),
)
.add_system_to_stage(
bevy_render::stage::POST_RENDER,
free_shared_buffers_system.system(),
);
app.add_system_to_stage(bevy_render::stage::RENDER, render_system)
.add_system_to_stage(bevy_render::stage::POST_RENDER, free_shared_buffers_system);
}
}

View file

@ -13,7 +13,6 @@ pub mod prelude {
}
use bevy_app::prelude::*;
use bevy_ecs::IntoSystem;
pub struct WindowPlugin {
pub add_primary_window: bool,
@ -54,7 +53,7 @@ impl Plugin for WindowPlugin {
}
if self.exit_on_close {
app.add_system(exit_on_window_close_system.system());
app.add_system(exit_on_window_close_system);
}
}
}

View file

@ -10,7 +10,7 @@ pub use winit_config::*;
pub use winit_windows::*;
use bevy_app::{prelude::*, AppExit};
use bevy_ecs::{IntoThreadLocalSystem, Resources, World};
use bevy_ecs::{Resources, World};
use bevy_math::Vec2;
use bevy_utils::tracing::trace;
use bevy_window::{
@ -36,7 +36,7 @@ impl Plugin for WinitPlugin {
// .add_event::<winit::event::WindowEvent>()
.init_resource::<WinitWindows>()
.set_runner(winit_runner)
.add_system(change_window.thread_local_system());
.add_system(change_window);
}
}

View file

@ -9,11 +9,11 @@ use std::{
fn main() {
App::build()
.add_plugins(DefaultPlugins)
.add_startup_system(setup.system())
.add_system(velocity_system.system())
.add_system(move_system.system())
.add_system(collision_system.system())
.add_system(select_system.system())
.add_startup_system(setup)
.add_system(velocity_system)
.add_system(move_system)
.add_system(collision_system)
.add_system(select_system)
.run();
}

View file

@ -3,7 +3,7 @@ use bevy::prelude::*;
fn main() {
App::build()
.add_plugins(DefaultPlugins)
.add_startup_system(setup.system())
.add_startup_system(setup)
.run();
}

View file

@ -3,8 +3,8 @@ use bevy::prelude::*;
fn main() {
App::build()
.add_plugins(DefaultPlugins)
.add_startup_system(setup.system())
.add_system(animate_sprite_system.system())
.add_startup_system(setup)
.add_system(animate_sprite_system)
.run();
}

View file

@ -5,8 +5,8 @@ fn main() {
App::build()
.init_resource::<RpgSpriteHandles>()
.add_plugins(DefaultPlugins)
.add_startup_system(setup.system())
.add_system(load_atlas.system())
.add_startup_system(setup)
.add_system(load_atlas)
.run();
}

View file

@ -4,7 +4,7 @@ fn main() {
App::build()
.add_resource(Msaa { samples: 4 })
.add_plugins(DefaultPlugins)
.add_startup_system(setup.system())
.add_startup_system(setup)
.run();
}

View file

@ -4,7 +4,7 @@ fn main() {
App::build()
.add_resource(Msaa { samples: 4 })
.add_plugins(DefaultPlugins)
.add_startup_system(setup.system())
.add_startup_system(setup)
.run();
}

View file

@ -7,7 +7,7 @@ fn main() {
App::build()
.add_resource(Msaa { samples: 4 })
.add_plugins(DefaultPlugins)
.add_startup_system(setup.system())
.add_startup_system(setup)
.run();
}

View file

@ -6,8 +6,8 @@ fn main() {
App::build()
.add_resource(Msaa { samples: 4 })
.add_plugins(DefaultPlugins)
.add_startup_system(setup.system())
.add_system(rotator_system.system())
.add_startup_system(setup)
.add_system(rotator_system)
.run();
}

View file

@ -13,8 +13,8 @@ fn main() {
.add_plugins(DefaultPlugins)
.add_plugin(FrameTimeDiagnosticsPlugin::default())
.add_plugin(PrintDiagnosticsPlugin::default())
.add_startup_system(setup.system())
.add_system(move_cubes.system())
.add_startup_system(setup)
.add_system(move_cubes)
.run();
}

View file

@ -4,7 +4,7 @@ use bevy::prelude::*;
fn main() {
App::build()
.add_plugins(DefaultPlugins)
.add_startup_system(setup.system())
.add_startup_system(setup)
.run();
}

View file

@ -10,9 +10,9 @@ use bevy::{
fn main() {
App::build()
.add_plugins(DefaultPlugins)
.add_startup_system(setup.system())
.add_system(rotator_system.system())
.add_system(camera_order_color_system.system())
.add_startup_system(setup)
.add_system(rotator_system)
.add_system(camera_order_color_system)
.run();
}

View file

@ -6,7 +6,7 @@ fn main() {
App::build()
.add_resource(Msaa { samples: 2 })
.add_plugins(DefaultPlugins)
.add_startup_system(setup.system())
.add_startup_system(setup)
.run();
}

View file

@ -26,6 +26,6 @@ fn main() {
App::build()
.add_resource(Input(String::new()))
.set_runner(my_runner)
.add_system(print_system.system())
.add_system(print_system)
.run();
}

View file

@ -14,7 +14,7 @@ fn main() {
App::build()
.add_resource(ScheduleRunnerSettings::run_once())
.add_plugins(MinimalPlugins)
.add_system(hello_world_system.system())
.add_system(hello_world_system)
.run();
// this app loops forever at 60 fps
@ -23,7 +23,7 @@ fn main() {
1.0 / 60.0,
)))
.add_plugins(MinimalPlugins)
.add_system(counter.system())
.add_system(counter)
.run();
}

View file

@ -9,7 +9,7 @@ fn main() {
// filter: "wgpu=warn,bevy_ecs=info".to_string(),
// })
.add_plugins(DefaultPlugins)
.add_system(log_system.system())
.add_system(log_system)
.run();
}

View file

@ -29,8 +29,7 @@ impl Plugin for PrintMessagePlugin {
message: self.message.clone(),
timer: Timer::new(self.wait_duration, true),
};
app.add_resource(state)
.add_system(print_message_system.system());
app.add_resource(state).add_system(print_message_system);
}
}

View file

@ -29,7 +29,7 @@ pub struct PrintHelloPlugin;
impl Plugin for PrintHelloPlugin {
fn build(&self, app: &mut AppBuilder) {
app.add_system(print_hello_system.system());
app.add_system(print_hello_system);
}
}
@ -41,7 +41,7 @@ pub struct PrintWorldPlugin;
impl Plugin for PrintWorldPlugin {
fn build(&self, app: &mut AppBuilder) {
app.add_system(print_world_system.system());
app.add_system(print_world_system);
}
}

View file

@ -5,7 +5,7 @@ fn main() {
App::build()
.add_resource(Msaa { samples: 4 })
.add_plugins(DefaultPlugins)
.add_startup_system(setup.system())
.add_startup_system(setup)
.run();
}

View file

@ -39,8 +39,8 @@ fn main() {
.init_resource::<State>()
.add_asset::<CustomAsset>()
.init_asset_loader::<CustomAssetLoader>()
.add_startup_system(setup.system())
.add_system(print_on_load.system())
.add_startup_system(setup)
.add_system(print_on_load)
.run();
}

View file

@ -6,7 +6,7 @@ use bevy::prelude::*;
fn main() {
App::build()
.add_plugins(DefaultPlugins)
.add_startup_system(setup.system())
.add_startup_system(setup)
.run();
}

View file

@ -4,7 +4,7 @@ use bevy::prelude::*;
fn main() {
App::build()
.add_plugins(DefaultPlugins)
.add_startup_system(setup.system())
.add_startup_system(setup)
.run();
}

View file

@ -9,8 +9,8 @@ fn main() {
.add_plugins(DefaultPlugins)
// The "print diagnostics" plugin is optional. It just visualizes our diagnostics in the console
.add_plugin(PrintDiagnosticsPlugin::default())
.add_startup_system(setup_diagnostic_system.system())
.add_system(my_system.system())
.add_startup_system(setup_diagnostic_system)
.add_system(my_system)
.run();
}

View file

@ -256,9 +256,9 @@ fn main() {
.init_resource::<GameState>()
// Startup systems run exactly once BEFORE all other systems. These are generally used for
// app initialization code (ex: adding entities and resources)
.add_startup_system(startup_system.system())
// my_system.system() calls converts normal rust functions into ECS systems:
.add_system(print_message_system.system())
.add_startup_system(startup_system)
// my_system calls converts normal rust functions into ECS systems:
.add_system(print_message_system)
//
// SYSTEM EXECUTION ORDER
//
@ -276,18 +276,18 @@ fn main() {
// This is where "stages" come in. A "stage" is a group of systems that execute (in parallel). Stages are executed in order,
// and the next stage won't start until all systems in the current stage have finished.
// add_system(system) adds systems to the UPDATE stage by default
// However we can manually specify the stage if we want to. The following is equivalent to add_system(score_system.system())
.add_system_to_stage(stage::UPDATE, score_system.system())
// However we can manually specify the stage if we want to. The following is equivalent to add_system(score_system)
.add_system_to_stage(stage::UPDATE, score_system)
// We can also create new stages. Here is what our games stage order will look like:
// "before_round": new_player_system, new_round_system
// "update": print_message_system, score_system
// "after_round": score_check_system, game_over_system
.add_stage_before(stage::UPDATE, "before_round")
.add_stage_after(stage::UPDATE, "after_round")
.add_system_to_stage("before_round", new_round_system.system())
.add_system_to_stage("before_round", new_player_system.system())
.add_system_to_stage("after_round", score_check_system.system())
.add_system_to_stage("after_round", game_over_system.system())
.add_system_to_stage("before_round", new_round_system)
.add_system_to_stage("before_round", new_player_system)
.add_system_to_stage("after_round", score_check_system)
.add_system_to_stage("after_round", game_over_system)
// score_check_system will run before game_over_system because score_check_system modifies GameState and game_over_system
// reads GameState. This works, but it's a bit confusing. In practice, it would be clearer to create a new stage that runs
// before "after_round"

View file

@ -7,8 +7,8 @@ fn main() {
.add_plugins(DefaultPlugins)
.add_event::<MyEvent>()
.init_resource::<EventTriggerState>()
.add_system(event_trigger_system.system())
.add_system(event_listener_system.system())
.add_system(event_trigger_system)
.add_system(event_listener_system)
.run();
}

View file

@ -3,8 +3,8 @@ use bevy::prelude::*;
fn main() {
App::build()
.add_plugins(DefaultPlugins)
.add_startup_system(setup.system())
.add_system(rotate.system())
.add_startup_system(setup)
.add_system(rotate)
.run();
}

View file

@ -74,8 +74,8 @@ fn bounce_system(
fn main() {
App::build()
.add_plugins(DefaultPlugins)
.add_startup_system(spawn_system.system())
.add_system(move_system.system())
.add_system(bounce_system.system())
.add_startup_system(spawn_system)
.add_system(move_system)
.add_system(bounce_system)
.run();
}

View file

@ -2,8 +2,8 @@ use bevy::prelude::*;
fn main() {
App::build()
.add_startup_system(startup_system.system())
.add_system(normal_system.system())
.add_startup_system(startup_system)
.add_system(normal_system)
.run();
}

View file

@ -0,0 +1,25 @@
use anyhow::Result;
use bevy::prelude::*;
fn main() {
App::build()
.add_resource(Message("hello".to_string()))
.add_system(parse_message_system.chain(handler_system))
.run();
}
struct Message(String);
// this system produces a Result<usize> output by trying to parse the Message resource
fn parse_message_system(message: Res<Message>) -> Result<usize> {
Ok(message.0.parse::<usize>()?)
}
// This system takes a Result<usize> input and either prints the parsed value or the error message
// Try changing the Message resource to something that isn't an integer. You should see the error message printed.
fn handler_system(In(result): In<Result<usize>>) {
match result {
Ok(value) => println!("parsed message: {}", value),
Err(err) => println!("encountered an error: {:?}", err),
}
}

View file

@ -10,11 +10,11 @@ fn main() {
.add_plugins(DefaultPlugins)
.add_resource(Scoreboard { score: 0 })
.add_resource(ClearColor(Color::rgb(0.9, 0.9, 0.9)))
.add_startup_system(setup.system())
.add_system(paddle_movement_system.system())
.add_system(ball_collision_system.system())
.add_system(ball_movement_system.system())
.add_system(scoreboard_system.system())
.add_startup_system(setup)
.add_system(paddle_movement_system)
.add_system(ball_collision_system)
.add_system(ball_movement_system)
.add_system(scoreboard_system)
.run();
}

View file

@ -1,7 +1,7 @@
use bevy::prelude::*;
fn main() {
App::build().add_system(hello_world_system.system()).run();
App::build().add_system(hello_world_system).run();
}
fn hello_world_system() {

View file

@ -3,7 +3,7 @@ use bevy::{prelude::*, window::ReceivedCharacter};
fn main() {
App::build()
.add_plugins(DefaultPlugins)
.add_system(print_char_event_system.system())
.add_system(print_char_event_system)
.run();
}

View file

@ -8,8 +8,8 @@ fn main() {
App::build()
.add_plugins(DefaultPlugins)
.init_resource::<GamepadLobby>()
.add_system_to_stage(stage::PRE_UPDATE, connection_system.system())
.add_system(gamepad_system.system())
.add_system_to_stage(stage::PRE_UPDATE, connection_system)
.add_system(gamepad_system)
.run();
}

View file

@ -6,7 +6,7 @@ use bevy::{
fn main() {
App::build()
.add_plugins(DefaultPlugins)
.add_system(gamepad_events.system())
.add_system(gamepad_events)
.run();
}

View file

@ -6,7 +6,7 @@ use bevy::{
fn main() {
App::build()
.add_plugins(DefaultPlugins)
.add_system(keyboard_input_system.system())
.add_system(keyboard_input_system)
.run();
}

View file

@ -3,7 +3,7 @@ use bevy::{input::keyboard::KeyboardInput, prelude::*};
fn main() {
App::build()
.add_plugins(DefaultPlugins)
.add_system(print_keyboard_event_system.system())
.add_system(print_keyboard_event_system)
.run();
}

View file

@ -3,7 +3,7 @@ use bevy::prelude::*;
fn main() {
App::build()
.add_plugins(DefaultPlugins)
.add_system(mouse_click_system.system())
.add_system(mouse_click_system)
.run();
}

View file

@ -7,7 +7,7 @@ use bevy::{
fn main() {
App::build()
.add_plugins(DefaultPlugins)
.add_system(print_mouse_events_system.system())
.add_system(print_mouse_events_system)
.run();
}

View file

@ -3,7 +3,7 @@ use bevy::{input::touch::*, prelude::*};
fn main() {
App::build()
.add_plugins(DefaultPlugins)
.add_system(touch_system.system())
.add_system(touch_system)
.run();
}

View file

@ -3,7 +3,7 @@ use bevy::{input::touch::*, prelude::*};
fn main() {
App::build()
.add_plugins(DefaultPlugins)
.add_system(touch_event_system.system())
.add_system(touch_event_system)
.run();
}

View file

@ -12,7 +12,7 @@ fn main() {
})
.add_resource(Msaa { samples: 4 })
.add_plugins(DefaultPlugins)
.add_startup_system(setup.system())
.add_startup_system(setup)
.run();
}
/// set up a simple 3D scene

View file

@ -16,7 +16,7 @@ fn main() {
.register_property::<Test>()
.register_property::<Nested>()
.register_property::<CustomProperty>()
.add_startup_system(setup.system())
.add_startup_system(setup)
.run();
}

View file

@ -11,10 +11,10 @@ fn main() {
// The core Bevy plugins already register their components, so you only need this step for custom components.
.register_component::<ComponentA>()
.register_component::<ComponentB>()
.add_startup_system(save_scene_system.thread_local_system())
.add_startup_system(load_scene_system.system())
.add_startup_system(infotext_system.system())
.add_system(print_system.system())
.add_startup_system(save_scene_system)
.add_startup_system(load_scene_system)
.add_startup_system(infotext_system)
.add_system(print_system)
.run();
}

View file

@ -15,7 +15,7 @@ fn main() {
App::build()
.add_plugins(DefaultPlugins)
.add_asset::<MyMaterialWithVertexColorSupport>()
.add_startup_system(setup.system())
.add_startup_system(setup)
.run();
}

View file

@ -15,7 +15,7 @@ fn main() {
App::build()
.add_plugins(DefaultPlugins)
.add_asset::<MyMaterial>()
.add_startup_system(setup.system())
.add_startup_system(setup)
.run();
}

View file

@ -16,11 +16,8 @@ fn main() {
App::build()
.add_plugins(DefaultPlugins)
.add_asset::<MyMaterial>()
.add_startup_system(setup.system())
.add_system_to_stage(
stage::POST_UPDATE,
asset_shader_defs_system::<MyMaterial>.system(),
)
.add_startup_system(setup)
.add_system_to_stage(stage::POST_UPDATE, asset_shader_defs_system::<MyMaterial>)
.run();
}

View file

@ -40,11 +40,11 @@ fn main() {
.add_plugin(FrameTimeDiagnosticsPlugin::default())
.add_resource(BevyCounter { count: 0 })
.init_resource::<BirdMaterial>()
.add_startup_system(setup.system())
.add_system(mouse_handler.system())
.add_system(movement_system.system())
.add_system(collision_system.system())
.add_system(counter_system.system())
.add_startup_system(setup)
.add_system(mouse_handler)
.add_system(movement_system)
.add_system(collision_system)
.add_system(counter_system)
.run();
}

View file

@ -5,8 +5,8 @@ fn main() {
App::build()
.add_plugins(DefaultPlugins)
.init_resource::<ButtonMaterials>()
.add_startup_system(setup.system())
.add_system(button_system.system())
.add_startup_system(setup)
.add_system(button_system)
.run();
}

View file

@ -5,9 +5,9 @@ fn main() {
App::build()
.init_resource::<State>()
.add_plugins(DefaultPlugins)
.add_startup_system(setup.system())
.add_system(text_update_system.system())
.add_system(atlas_render_system.system())
.add_startup_system(setup)
.add_system(text_update_system)
.add_system(atlas_render_system)
.run();
}

View file

@ -8,8 +8,8 @@ fn main() {
App::build()
.add_plugins(DefaultPlugins)
.add_plugin(FrameTimeDiagnosticsPlugin::default())
.add_startup_system(setup.system())
.add_system(text_update_system.system())
.add_startup_system(setup)
.add_system(text_update_system)
.run();
}

View file

@ -5,8 +5,8 @@ extern crate rand;
fn main() {
App::build()
.add_plugins(DefaultPlugins)
.add_startup_system(infotext_system.system())
.add_system(change_text_system.system())
.add_startup_system(infotext_system)
.add_system(change_text_system)
.run();
}

View file

@ -4,7 +4,7 @@ use bevy::prelude::*;
fn main() {
App::build()
.add_plugins(DefaultPlugins)
.add_startup_system(setup.system())
.add_startup_system(setup)
.run();
}

View file

@ -13,8 +13,8 @@ fn main() {
.add_plugins(DefaultPlugins)
.add_asset::<RustSourceCode>()
.init_asset_loader::<RustSourceCodeLoader>()
.add_startup_system(load_asset.system())
.add_system(print_asset.system())
.add_startup_system(load_asset)
.add_system(print_asset)
.run();
}

View file

@ -12,8 +12,8 @@ fn main() {
)))
.add_plugin(ScheduleRunnerPlugin::default())
.add_plugin(LogPlugin::default())
.add_startup_system(hello_world_system.system())
.add_system(counter.system())
.add_startup_system(hello_world_system)
.add_system(counter)
.run();
}

View file

@ -3,7 +3,7 @@ use bevy::{log::LogPlugin, prelude::*};
fn main() {
App::build()
.add_plugin(LogPlugin::default())
.add_system(hello_wasm_system.system())
.add_system(hello_wasm_system)
.run();
}

View file

@ -15,12 +15,12 @@ fn main() {
})
.add_plugins(DefaultPlugins)
// One time greet
.add_startup_system(hello_wasm_system.system())
.add_startup_system(hello_wasm_system)
// Track ticks (sanity check, whether game loop is running)
.add_system(counter.system())
.add_system(counter)
// Track input events
.init_resource::<TrackInputState>()
.add_system(track_input_events.system())
.add_system(track_input_events)
.run();
}

View file

@ -17,7 +17,7 @@ fn main() {
App::build()
.add_resource(Msaa { samples: 4 })
.add_plugins(DefaultPlugins)
.add_startup_system(setup.system())
.add_startup_system(setup)
.run();
}

View file

@ -12,8 +12,8 @@ fn main() {
..Default::default()
})
.add_plugins(DefaultPlugins)
.add_system(change_title.system())
.add_system(toggle_cursor.system())
.add_system(change_title)
.add_system(toggle_cursor)
.run();
}