Make EventReader a SystemParam (#1244)

* Add generic support for `#[derive(SystemParam)]`
* Make EventReader a SystemParam
This commit is contained in:
TheRawMeatball 2021-01-19 09:23:30 +03:00 committed by GitHub
parent 71c6a19ed8
commit a880b54508
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 236 additions and 364 deletions

View File

@ -1,4 +1,4 @@
use bevy_ecs::ResMut; use bevy_ecs::{Local, Res, ResMut, SystemParam};
use bevy_utils::tracing::trace; use bevy_utils::tracing::trace;
use std::{fmt, marker::PhantomData}; use std::{fmt, marker::PhantomData};
@ -122,56 +122,59 @@ fn map_instance_event<T>(event_instance: &EventInstance<T>) -> &T {
} }
/// Reads events of type `T` in order and tracks which events have already been read. /// Reads events of type `T` in order and tracks which events have already been read.
pub struct EventReader<T> { #[derive(SystemParam)]
pub struct EventReader<'a, T: bevy_ecs::Resource> {
last_event_count: Local<'a, (usize, PhantomData<T>)>,
events: Res<'a, Events<T>>,
}
pub struct ManualEventReader<T> {
last_event_count: usize, last_event_count: usize,
_marker: PhantomData<T>, _marker: PhantomData<T>,
} }
impl<T> Default for EventReader<T> { impl<T> Default for ManualEventReader<T> {
fn default() -> Self { fn default() -> Self {
Self { ManualEventReader {
last_event_count: 0, last_event_count: 0,
_marker: PhantomData::default(), _marker: Default::default(),
} }
} }
} }
impl<T> EventReader<T> { impl<T> ManualEventReader<T> {
/// Iterates over the events this EventReader has not seen yet. This updates the EventReader's /// See [`EventReader::iter`]
/// event counter, which means subsequent event reads will not include events that happened before now.
pub fn iter<'a>(&mut self, events: &'a Events<T>) -> impl DoubleEndedIterator<Item = &'a T> { pub fn iter<'a>(&mut self, events: &'a Events<T>) -> impl DoubleEndedIterator<Item = &'a T> {
self.iter_with_id(events).map(|(event, _id)| event) internal_event_reader(&mut self.last_event_count, events).map(|(e, _)| e)
} }
/// Like [`iter`](Self::iter), except also returning the [`EventId`] of the events. /// See [`EventReader::iter_with_id`]
pub fn iter_with_id<'a>( pub fn iter_with_id<'a>(
&mut self, &mut self,
events: &'a Events<T>, events: &'a Events<T>,
) -> impl DoubleEndedIterator<Item = (&'a T, EventId<T>)> { ) -> impl DoubleEndedIterator<Item = (&'a T, EventId<T>)> {
self.iter_internal(events).map(|(event, id)| { internal_event_reader(&mut self.last_event_count, events)
trace!("EventReader::iter() -> {}", id); }
(event, id)
})
} }
/// Like [`iter_with_id`](Self::iter_with_id) except not emitting any traces for read messages. /// Like [`iter_with_id`](EventReader::iter_with_id) except not emitting any traces for read messages.
fn iter_internal<'a>( fn internal_event_reader<'a, T>(
&mut self, last_event_count: &mut usize,
events: &'a Events<T>, events: &'a Events<T>,
) -> impl DoubleEndedIterator<Item = (&'a T, EventId<T>)> { ) -> impl DoubleEndedIterator<Item = (&'a T, EventId<T>)> {
// if the reader has seen some of the events in a buffer, find the proper index offset. // if the reader has seen some of the events in a buffer, find the proper index offset.
// otherwise read all events in the buffer // otherwise read all events in the buffer
let a_index = if self.last_event_count > events.a_start_event_count { let a_index = if *last_event_count > events.a_start_event_count {
self.last_event_count - events.a_start_event_count *last_event_count - events.a_start_event_count
} else { } else {
0 0
}; };
let b_index = if self.last_event_count > events.b_start_event_count { let b_index = if *last_event_count > events.b_start_event_count {
self.last_event_count - events.b_start_event_count *last_event_count - events.b_start_event_count
} else { } else {
0 0
}; };
self.last_event_count = events.event_count; *last_event_count = events.event_count;
match events.state { match events.state {
State::A => events State::A => events
.events_b .events_b
@ -204,56 +207,17 @@ impl<T> EventReader<T> {
} }
} }
/// Retrieves the latest event that this EventReader hasn't seen yet. This updates the EventReader's impl<'a, T: bevy_ecs::Resource> EventReader<'a, T> {
/// Iterates over the events this EventReader has not seen yet. This updates the EventReader's
/// event counter, which means subsequent event reads will not include events that happened before now. /// event counter, which means subsequent event reads will not include events that happened before now.
pub fn latest<'a>(&mut self, events: &'a Events<T>) -> Option<&'a T> { pub fn iter(&mut self) -> impl DoubleEndedIterator<Item = &T> {
self.latest_with_id(events).map(|(event, _)| event) self.iter_with_id().map(|(event, _id)| event)
} }
/// Like [`latest`](Self::latest), except also returning the [`EventId`] of the event. /// Like [`iter`](Self::iter), except also returning the [`EventId`] of the events.
pub fn latest_with_id<'a>(&mut self, events: &'a Events<T>) -> Option<(&'a T, EventId<T>)> { pub fn iter_with_id(&mut self) -> impl DoubleEndedIterator<Item = (&T, EventId<T>)> {
self.iter_internal(events).rev().next().map(|(event, id)| { internal_event_reader(&mut self.last_event_count.0, &self.events).map(|(event, id)| {
trace!("EventReader::latest() -> {}", id); trace!("EventReader::iter() -> {}", id);
(event, id)
})
}
/// Retrieves the latest event that matches the given `predicate` that this reader hasn't seen yet. This updates the EventReader's
/// event counter, which means subsequent event reads will not include events that happened before now.
pub fn find_latest<'a>(
&mut self,
events: &'a Events<T>,
predicate: impl FnMut(&&T) -> bool,
) -> Option<&'a T> {
self.find_latest_with_id(events, predicate)
.map(|(event, _)| event)
}
/// Like [`find_latest`](Self::find_latest), except also returning the [`EventId`] of the event.
pub fn find_latest_with_id<'a>(
&mut self,
events: &'a Events<T>,
mut predicate: impl FnMut(&&T) -> bool,
) -> Option<(&'a T, EventId<T>)> {
self.iter_internal(events)
.rev()
.find(|(event, _id)| predicate(event))
.map(|(event, id)| {
trace!("EventReader::find_latest() -> {}", id);
(event, id)
})
}
/// Retrieves the earliest event in `events` that this reader hasn't seen yet. This updates the EventReader's
/// event counter, which means subsequent event reads will not include events that happened before now.
pub fn earliest<'a>(&mut self, events: &'a Events<T>) -> Option<&'a T> {
self.earliest_with_id(events).map(|(event, _)| event)
}
/// Like [`earliest`](Self::earliest), except also returning the [`EventId`] of the event.
pub fn earliest_with_id<'a>(&mut self, events: &'a Events<T>) -> Option<(&'a T, EventId<T>)> {
self.iter_internal(events).next().map(|(event, id)| {
trace!("EventReader::earliest() -> {}", id);
(event, id) (event, id)
}) })
} }
@ -278,17 +242,17 @@ impl<T: bevy_ecs::Resource> Events<T> {
self.event_count += 1; self.event_count += 1;
} }
/// Gets a new [EventReader]. This will include all events already in the event buffers. /// Gets a new [ManualEventReader]. This will include all events already in the event buffers.
pub fn get_reader(&self) -> EventReader<T> { pub fn get_reader(&self) -> ManualEventReader<T> {
EventReader { ManualEventReader {
last_event_count: 0, last_event_count: 0,
_marker: PhantomData, _marker: PhantomData,
} }
} }
/// Gets a new [EventReader]. This will ignore all events already in the event buffers. It will read all future events. /// Gets a new [ManualEventReader]. This will ignore all events already in the event buffers. It will read all future events.
pub fn get_reader_current(&self) -> EventReader<T> { pub fn get_reader_current(&self) -> ManualEventReader<T> {
EventReader { ManualEventReader {
last_event_count: self.event_count, last_event_count: self.event_count,
_marker: PhantomData, _marker: PhantomData,
} }
@ -461,7 +425,7 @@ mod tests {
fn get_events( fn get_events(
events: &Events<TestEvent>, events: &Events<TestEvent>,
reader: &mut EventReader<TestEvent>, reader: &mut ManualEventReader<TestEvent>,
) -> Vec<TestEvent> { ) -> Vec<TestEvent> {
reader.iter(events).cloned().collect::<Vec<TestEvent>>() reader.iter(events).cloned().collect::<Vec<TestEvent>>()
} }

View File

@ -1,9 +1,5 @@
use super::{App, AppBuilder}; use super::{App, AppBuilder};
use crate::{ use crate::{app::AppExit, event::Events, plugin::Plugin, ManualEventReader};
app::AppExit,
event::{EventReader, Events},
plugin::Plugin,
};
use bevy_utils::{Duration, Instant}; use bevy_utils::{Duration, Instant};
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
@ -56,7 +52,7 @@ impl Plugin for ScheduleRunnerPlugin {
.get_or_insert_with(ScheduleRunnerSettings::default) .get_or_insert_with(ScheduleRunnerSettings::default)
.to_owned(); .to_owned();
app.set_runner(move |mut app: App| { app.set_runner(move |mut app: App| {
let mut app_exit_event_reader = EventReader::<AppExit>::default(); let mut app_exit_event_reader = ManualEventReader::<AppExit>::default();
match settings.run_mode { match settings.run_mode {
RunMode::Once => { RunMode::Once => {
app.update(); app.update();
@ -68,7 +64,8 @@ impl Plugin for ScheduleRunnerPlugin {
let start_time = Instant::now(); let start_time = Instant::now();
if let Some(app_exit_events) = app.resources.get_mut::<Events<AppExit>>() { if let Some(app_exit_events) = app.resources.get_mut::<Events<AppExit>>() {
if let Some(exit) = app_exit_event_reader.latest(&app_exit_events) { if let Some(exit) = app_exit_event_reader.iter(&app_exit_events).last()
{
return Err(exit.clone()); return Err(exit.clone());
} }
} }
@ -76,7 +73,8 @@ impl Plugin for ScheduleRunnerPlugin {
app.update(); app.update();
if let Some(app_exit_events) = app.resources.get_mut::<Events<AppExit>>() { if let Some(app_exit_events) = app.resources.get_mut::<Events<AppExit>>() {
if let Some(exit) = app_exit_event_reader.latest(&app_exit_events) { if let Some(exit) = app_exit_event_reader.iter(&app_exit_events).last()
{
return Err(exit.clone()); return Err(exit.clone());
} }
} }

View File

@ -23,8 +23,8 @@ use proc_macro::TokenStream;
use proc_macro2::{Span, TokenStream as TokenStream2}; use proc_macro2::{Span, TokenStream as TokenStream2};
use quote::quote; use quote::quote;
use syn::{ use syn::{
parse::ParseStream, parse_macro_input, Data, DataStruct, DeriveInput, Error, Field, Fields, parse::ParseStream, parse_macro_input, punctuated::Punctuated, Data, DataStruct, DeriveInput,
Ident, Index, Lifetime, Path, Result, Error, Field, Fields, GenericParam, Ident, Index, Lifetime, Path, Result, Token,
}; };
/// Implement `Bundle` for a monomorphic struct /// Implement `Bundle` for a monomorphic struct
@ -410,16 +410,44 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
let generics = ast.generics; 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 lifetimeless_generics: Vec<_> = generics
.params
.iter()
.filter(|g| matches!(g, GenericParam::Type(_)))
.collect();
let phantoms = lifetimeless_generics
.iter()
.map(|g| {
let g = match g {
GenericParam::Type(g) => &g.ident,
_ => panic!(),
};
quote! { ::std::marker::PhantomData::<#g>, }
})
.fold(quote!(), |old, new| {
quote! { #old #new }
});
let mut punctuated_generics = Punctuated::<_, Token![,]>::new();
punctuated_generics.extend(lifetimeless_generics.iter());
let mut punctuated_generic_idents = Punctuated::<_, Token![,]>::new();
punctuated_generic_idents.extend(lifetimeless_generics.iter().map(|g| match g {
GenericParam::Type(g) => &g.ident,
_ => panic!(),
}));
let struct_name = &ast.ident; let struct_name = &ast.ident;
let fetch_struct_name = Ident::new(&format!("Fetch{}", struct_name), Span::call_site()); let fetch_struct_name = Ident::new(&format!("Fetch{}", struct_name), Span::call_site());
TokenStream::from(quote! { TokenStream::from(quote! {
pub struct #fetch_struct_name; pub struct #fetch_struct_name<#punctuated_generics>(#phantoms);
impl #impl_generics #path::SystemParam for #struct_name#ty_generics #where_clause { impl #impl_generics #path::SystemParam for #struct_name#ty_generics #where_clause {
type Fetch = #fetch_struct_name; type Fetch = #fetch_struct_name <#punctuated_generic_idents>;
} }
impl #impl_generics #path::FetchSystemParam<'a> for #fetch_struct_name { impl #impl_generics #path::FetchSystemParam<'a> for #fetch_struct_name<#punctuated_generic_idents> {
type Item = #struct_name#ty_generics; type Item = #struct_name#ty_generics;
fn init(system_state: &mut #path::SystemState, world: &#path::World, resources: &mut #path::Resources) { fn init(system_state: &mut #path::SystemState, world: &#path::World, resources: &mut #path::Resources) {
#(<<#field_types as SystemParam>::Fetch as #path::FetchSystemParam>::init(system_state, world, resources);)* #(<<#field_types as SystemParam>::Fetch as #path::FetchSystemParam>::init(system_state, world, resources);)*

View File

@ -1,6 +1,6 @@
use crate::{Axis, Input}; use crate::{Axis, Input};
use bevy_app::{EventReader, Events}; use bevy_app::{EventReader, Events};
use bevy_ecs::{Local, Res, ResMut}; use bevy_ecs::{Res, ResMut};
use bevy_utils::HashMap; use bevy_utils::HashMap;
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
@ -202,16 +202,15 @@ impl ButtonAxisSettings {
} }
pub fn gamepad_event_system( pub fn gamepad_event_system(
mut event_reader: Local<EventReader<GamepadEventRaw>>,
mut button_input: ResMut<Input<GamepadButton>>, mut button_input: ResMut<Input<GamepadButton>>,
mut axis: ResMut<Axis<GamepadAxis>>, mut axis: ResMut<Axis<GamepadAxis>>,
mut button_axis: ResMut<Axis<GamepadButton>>, mut button_axis: ResMut<Axis<GamepadButton>>,
raw_events: Res<Events<GamepadEventRaw>>, mut raw_events: EventReader<GamepadEventRaw>,
mut events: ResMut<Events<GamepadEvent>>, mut events: ResMut<Events<GamepadEvent>>,
settings: Res<GamepadSettings>, settings: Res<GamepadSettings>,
) { ) {
button_input.update(); button_input.update();
for event in event_reader.iter(&raw_events) { for event in raw_events.iter() {
let (gamepad, event) = (event.0, &event.1); let (gamepad, event) = (event.0, &event.1);
match event { match event {
GamepadEventType::Connected => { GamepadEventType::Connected => {

View File

@ -1,6 +1,6 @@
use crate::{ElementState, Input}; use crate::{ElementState, Input};
use bevy_app::prelude::*; use bevy_app::prelude::*;
use bevy_ecs::{Local, Res, ResMut}; use bevy_ecs::ResMut;
/// A key input event from a keyboard device /// A key input event from a keyboard device
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -10,23 +10,13 @@ pub struct KeyboardInput {
pub state: ElementState, pub state: ElementState,
} }
/// State used by the keyboard input system
#[derive(Default)]
pub struct KeyboardInputState {
keyboard_input_event_reader: EventReader<KeyboardInput>,
}
/// Updates the Input<KeyCode> resource with the latest KeyboardInput events /// Updates the Input<KeyCode> resource with the latest KeyboardInput events
pub fn keyboard_input_system( pub fn keyboard_input_system(
mut state: Local<KeyboardInputState>,
mut keyboard_input: ResMut<Input<KeyCode>>, mut keyboard_input: ResMut<Input<KeyCode>>,
keyboard_input_events: Res<Events<KeyboardInput>>, mut keyboard_input_events: EventReader<KeyboardInput>,
) { ) {
keyboard_input.update(); keyboard_input.update();
for event in state for event in keyboard_input_events.iter() {
.keyboard_input_event_reader
.iter(&keyboard_input_events)
{
if let KeyboardInput { if let KeyboardInput {
key_code: Some(key_code), key_code: Some(key_code),
state, state,

View File

@ -1,6 +1,6 @@
use crate::{ElementState, Input}; use crate::{ElementState, Input};
use bevy_app::prelude::{EventReader, Events}; use bevy_app::prelude::EventReader;
use bevy_ecs::{Local, Res, ResMut}; use bevy_ecs::ResMut;
use bevy_math::Vec2; use bevy_math::Vec2;
/// A mouse button input event /// A mouse button input event
@ -41,23 +41,13 @@ pub struct MouseWheel {
pub y: f32, pub y: f32,
} }
/// State used by the mouse button input system
#[derive(Default)]
pub struct MouseButtonInputState {
mouse_button_input_event_reader: EventReader<MouseButtonInput>,
}
/// Updates the Input<MouseButton> resource with the latest MouseButtonInput events /// Updates the Input<MouseButton> resource with the latest MouseButtonInput events
pub fn mouse_button_input_system( pub fn mouse_button_input_system(
mut state: Local<MouseButtonInputState>,
mut mouse_button_input: ResMut<Input<MouseButton>>, mut mouse_button_input: ResMut<Input<MouseButton>>,
mouse_button_input_events: Res<Events<MouseButtonInput>>, mut mouse_button_input_events: EventReader<MouseButtonInput>,
) { ) {
mouse_button_input.update(); mouse_button_input.update();
for event in state for event in mouse_button_input_events.iter() {
.mouse_button_input_event_reader
.iter(&mouse_button_input_events)
{
match event.state { match event.state {
ElementState::Pressed => mouse_button_input.press(event.button), ElementState::Pressed => mouse_button_input.press(event.button),
ElementState::Released => mouse_button_input.release(event.button), ElementState::Released => mouse_button_input.release(event.button),

View File

@ -6,21 +6,14 @@ use bevy_app::{
prelude::{EventReader, Events}, prelude::{EventReader, Events},
AppExit, AppExit,
}; };
use bevy_ecs::{Local, Res, ResMut}; use bevy_ecs::ResMut;
/// Local "exit on escape" system state
#[derive(Default)]
pub struct ExitOnEscapeState {
reader: EventReader<KeyboardInput>,
}
/// Sends the AppExit event whenever the "esc" key is pressed. /// Sends the AppExit event whenever the "esc" key is pressed.
pub fn exit_on_esc_system( pub fn exit_on_esc_system(
mut state: Local<ExitOnEscapeState>, mut keyboard_input_events: EventReader<KeyboardInput>,
keyboard_input_events: Res<Events<KeyboardInput>>,
mut app_exit_events: ResMut<Events<AppExit>>, mut app_exit_events: ResMut<Events<AppExit>>,
) { ) {
for event in state.reader.iter(&keyboard_input_events) { for event in keyboard_input_events.iter() {
if let Some(key_code) = event.key_code { if let Some(key_code) = event.key_code {
if event.state == ElementState::Pressed && key_code == KeyCode::Escape { if event.state == ElementState::Pressed && key_code == KeyCode::Escape {
app_exit_events.send(AppExit); app_exit_events.send(AppExit);

View File

@ -1,5 +1,5 @@
use bevy_app::{EventReader, Events}; use bevy_app::EventReader;
use bevy_ecs::{Local, Res, ResMut}; use bevy_ecs::ResMut;
use bevy_math::Vec2; use bevy_math::Vec2;
use bevy_utils::HashMap; use bevy_utils::HashMap;
@ -77,11 +77,6 @@ pub enum TouchPhase {
Cancelled, Cancelled,
} }
#[derive(Default)]
pub struct TouchSystemState {
touch_event_reader: EventReader<TouchInput>,
}
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub struct Touch { pub struct Touch {
id: u64, id: u64,
@ -226,13 +221,12 @@ impl Touches {
/// Updates the Touches resource with the latest TouchInput events /// Updates the Touches resource with the latest TouchInput events
pub fn touch_screen_input_system( pub fn touch_screen_input_system(
mut state: Local<TouchSystemState>,
mut touch_state: ResMut<Touches>, mut touch_state: ResMut<Touches>,
touch_input_events: Res<Events<TouchInput>>, mut touch_input_events: EventReader<TouchInput>,
) { ) {
touch_state.update(); touch_state.update();
for event in state.touch_event_reader.iter(&touch_input_events) { for event in touch_input_events.iter() {
touch_state.process_touch_event(event); touch_state.process_touch_event(event);
} }
} }

View File

@ -1,6 +1,6 @@
use super::CameraProjection; use super::CameraProjection;
use bevy_app::prelude::{EventReader, Events}; use bevy_app::prelude::EventReader;
use bevy_ecs::{Added, Component, Entity, Local, Query, QuerySet, Res}; use bevy_ecs::{Added, Component, Entity, Query, QuerySet, Res};
use bevy_math::Mat4; use bevy_math::Mat4;
use bevy_reflect::{Reflect, ReflectComponent}; use bevy_reflect::{Reflect, ReflectComponent};
use bevy_window::{WindowCreated, WindowId, WindowResized, Windows}; use bevy_window::{WindowCreated, WindowId, WindowResized, Windows};
@ -28,16 +28,9 @@ impl Default for DepthCalculation {
} }
} }
#[derive(Default)]
pub struct CameraSystemState {
window_resized_event_reader: EventReader<WindowResized>,
window_created_event_reader: EventReader<WindowCreated>,
}
pub fn camera_system<T: CameraProjection + Component>( pub fn camera_system<T: CameraProjection + Component>(
mut state: Local<CameraSystemState>, mut window_resized_events: EventReader<WindowResized>,
window_resized_events: Res<Events<WindowResized>>, mut window_created_events: EventReader<WindowCreated>,
window_created_events: Res<Events<WindowCreated>>,
windows: Res<Windows>, windows: Res<Windows>,
mut queries: QuerySet<( mut queries: QuerySet<(
Query<(Entity, &mut Camera, &mut T)>, Query<(Entity, &mut Camera, &mut T)>,
@ -46,11 +39,7 @@ pub fn camera_system<T: CameraProjection + Component>(
) { ) {
let mut changed_window_ids = Vec::new(); let mut changed_window_ids = Vec::new();
// handle resize events. latest events are handled first because we only want to resize each window once // handle resize events. latest events are handled first because we only want to resize each window once
for event in state for event in window_resized_events.iter().rev() {
.window_resized_event_reader
.iter(&window_resized_events)
.rev()
{
if changed_window_ids.contains(&event.id) { if changed_window_ids.contains(&event.id) {
continue; continue;
} }
@ -59,11 +48,7 @@ pub fn camera_system<T: CameraProjection + Component>(
} }
// handle resize events. latest events are handled first because we only want to resize each window once // handle resize events. latest events are handled first because we only want to resize each window once
for event in state for event in window_created_events.iter().rev() {
.window_created_event_reader
.iter(&window_created_events)
.rev()
{
if changed_window_ids.contains(&event.id) { if changed_window_ids.contains(&event.id) {
continue; continue;
} }

View File

@ -51,7 +51,6 @@ use shader::ShaderLoader;
use texture::HdrTextureLoader; use texture::HdrTextureLoader;
#[cfg(feature = "png")] #[cfg(feature = "png")]
use texture::ImageTextureLoader; use texture::ImageTextureLoader;
use texture::TextureResourceSystemState;
/// The names of "render" App stages /// The names of "render" App stages
pub mod stage { pub mod stage {
@ -133,7 +132,6 @@ impl Plugin for RenderPlugin {
.init_resource::<RenderGraph>() .init_resource::<RenderGraph>()
.init_resource::<PipelineCompiler>() .init_resource::<PipelineCompiler>()
.init_resource::<RenderResourceBindings>() .init_resource::<RenderResourceBindings>()
.init_resource::<TextureResourceSystemState>()
.init_resource::<AssetRenderResourceBindings>() .init_resource::<AssetRenderResourceBindings>()
.init_resource::<ActiveCameras>() .init_resource::<ActiveCameras>()
.add_system_to_stage( .add_system_to_stage(

View File

@ -2,7 +2,7 @@ use crate::{
pipeline::{IndexFormat, PrimitiveTopology, RenderPipelines, VertexFormat}, pipeline::{IndexFormat, PrimitiveTopology, RenderPipelines, VertexFormat},
renderer::{BufferInfo, BufferUsage, RenderResourceContext, RenderResourceId}, renderer::{BufferInfo, BufferUsage, RenderResourceContext, RenderResourceId},
}; };
use bevy_app::prelude::{EventReader, Events}; use bevy_app::prelude::EventReader;
use bevy_asset::{AssetEvent, Assets, Handle}; use bevy_asset::{AssetEvent, Assets, Handle};
use bevy_core::AsBytes; use bevy_core::AsBytes;
use bevy_ecs::{Changed, Entity, Local, Mut, Query, QuerySet, Res, With}; use bevy_ecs::{Changed, Entity, Local, Mut, Query, QuerySet, Res, With};
@ -349,7 +349,6 @@ pub struct MeshEntities {
#[derive(Default)] #[derive(Default)]
pub struct MeshResourceProviderState { pub struct MeshResourceProviderState {
mesh_event_reader: EventReader<AssetEvent<Mesh>>,
mesh_entities: HashMap<Handle<Mesh>, MeshEntities>, mesh_entities: HashMap<Handle<Mesh>, MeshEntities>,
} }
@ -357,7 +356,7 @@ pub fn mesh_resource_provider_system(
mut state: Local<MeshResourceProviderState>, mut state: Local<MeshResourceProviderState>,
render_resource_context: Res<Box<dyn RenderResourceContext>>, render_resource_context: Res<Box<dyn RenderResourceContext>>,
meshes: Res<Assets<Mesh>>, meshes: Res<Assets<Mesh>>,
mesh_events: Res<Events<AssetEvent<Mesh>>>, mut mesh_events: EventReader<AssetEvent<Mesh>>,
mut queries: QuerySet<( mut queries: QuerySet<(
Query<&mut RenderPipelines, With<Handle<Mesh>>>, Query<&mut RenderPipelines, With<Handle<Mesh>>>,
Query<(Entity, &Handle<Mesh>, &mut RenderPipelines), Changed<Handle<Mesh>>>, Query<(Entity, &Handle<Mesh>, &mut RenderPipelines), Changed<Handle<Mesh>>>,
@ -365,7 +364,7 @@ pub fn mesh_resource_provider_system(
) { ) {
let mut changed_meshes = HashSet::default(); let mut changed_meshes = HashSet::default();
let render_resource_context = &**render_resource_context; let render_resource_context = &**render_resource_context;
for event in state.mesh_event_reader.iter(&mesh_events) { for event in mesh_events.iter() {
match event { match event {
AssetEvent::Created { ref handle } => { AssetEvent::Created { ref handle } => {
changed_meshes.insert(handle.clone_weak()); changed_meshes.insert(handle.clone_weak());

View File

@ -9,7 +9,7 @@ use crate::{
texture, texture,
}; };
use bevy_app::{EventReader, Events}; use bevy_app::EventReader;
use bevy_asset::{Asset, AssetEvent, Assets, Handle, HandleId}; use bevy_asset::{Asset, AssetEvent, Assets, Handle, HandleId};
use bevy_ecs::{ use bevy_ecs::{
BoxedSystem, Changed, Commands, Entity, IntoSystem, Local, Or, Query, QuerySet, Res, ResMut, BoxedSystem, Changed, Commands, Entity, IntoSystem, Local, Or, Query, QuerySet, Res, ResMut,
@ -600,14 +600,14 @@ where
} }
struct AssetRenderNodeState<T: Asset> { struct AssetRenderNodeState<T: Asset> {
event_reader: EventReader<AssetEvent<T>>,
assets_waiting_for_textures: Vec<HandleId>, assets_waiting_for_textures: Vec<HandleId>,
_marker: PhantomData<T>,
} }
impl<T: Asset> Default for AssetRenderNodeState<T> { impl<T: Asset> Default for AssetRenderNodeState<T> {
fn default() -> Self { fn default() -> Self {
Self { Self {
event_reader: Default::default(), _marker: Default::default(),
assets_waiting_for_textures: Default::default(), assets_waiting_for_textures: Default::default(),
} }
} }
@ -618,7 +618,7 @@ fn asset_render_resources_node_system<T: RenderResources + Asset>(
mut state: Local<RenderResourcesNodeState<HandleId, T>>, mut state: Local<RenderResourcesNodeState<HandleId, T>>,
mut asset_state: Local<AssetRenderNodeState<T>>, mut asset_state: Local<AssetRenderNodeState<T>>,
assets: Res<Assets<T>>, assets: Res<Assets<T>>,
asset_events: Res<Events<AssetEvent<T>>>, mut asset_events: EventReader<AssetEvent<T>>,
mut asset_render_resource_bindings: ResMut<AssetRenderResourceBindings>, mut asset_render_resource_bindings: ResMut<AssetRenderResourceBindings>,
render_resource_context: Res<Box<dyn RenderResourceContext>>, render_resource_context: Res<Box<dyn RenderResourceContext>>,
mut queries: QuerySet<( mut queries: QuerySet<(
@ -632,7 +632,7 @@ fn asset_render_resources_node_system<T: RenderResources + Asset>(
let render_resource_context = &**render_resource_context; let render_resource_context = &**render_resource_context;
let mut changed_assets = HashMap::default(); let mut changed_assets = HashMap::default();
for event in asset_state.event_reader.iter(&asset_events) { for event in asset_events.iter() {
match event { match event {
AssetEvent::Created { ref handle } => { AssetEvent::Created { ref handle } => {
if let Some(asset) = assets.get(handle) { if let Some(asset) = assets.get(handle) {

View File

@ -3,14 +3,14 @@ use crate::{
renderer::{BufferInfo, BufferUsage, RenderContext}, renderer::{BufferInfo, BufferUsage, RenderContext},
texture::{Texture, TextureDescriptor, TEXTURE_ASSET_INDEX}, texture::{Texture, TextureDescriptor, TEXTURE_ASSET_INDEX},
}; };
use bevy_app::prelude::{EventReader, Events}; use bevy_app::{prelude::Events, ManualEventReader};
use bevy_asset::{AssetEvent, Assets}; use bevy_asset::{AssetEvent, Assets};
use bevy_ecs::{Resources, World}; use bevy_ecs::{Resources, World};
use bevy_utils::HashSet; use bevy_utils::HashSet;
#[derive(Default)] #[derive(Default)]
pub struct TextureCopyNode { pub struct TextureCopyNode {
pub texture_event_reader: EventReader<AssetEvent<Texture>>, pub texture_event_reader: ManualEventReader<AssetEvent<Texture>>,
} }
impl Node for TextureCopyNode { impl Node for TextureCopyNode {

View File

@ -2,15 +2,15 @@ use crate::{
render_graph::{Node, ResourceSlotInfo, ResourceSlots}, render_graph::{Node, ResourceSlotInfo, ResourceSlots},
renderer::{RenderContext, RenderResourceId, RenderResourceType}, renderer::{RenderContext, RenderResourceId, RenderResourceType},
}; };
use bevy_app::prelude::{EventReader, Events}; use bevy_app::{prelude::Events, ManualEventReader};
use bevy_ecs::{Resources, World}; use bevy_ecs::{Resources, World};
use bevy_window::{WindowCreated, WindowId, WindowResized, Windows}; use bevy_window::{WindowCreated, WindowId, WindowResized, Windows};
use std::borrow::Cow; use std::borrow::Cow;
pub struct WindowSwapChainNode { pub struct WindowSwapChainNode {
window_id: WindowId, window_id: WindowId,
window_created_event_reader: EventReader<WindowCreated>, window_created_event_reader: ManualEventReader<WindowCreated>,
window_resized_event_reader: EventReader<WindowResized>, window_resized_event_reader: ManualEventReader<WindowResized>,
} }
impl WindowSwapChainNode { impl WindowSwapChainNode {
@ -56,12 +56,12 @@ impl Node for WindowSwapChainNode {
// create window swapchain when window is resized or created // create window swapchain when window is resized or created
if self if self
.window_created_event_reader .window_created_event_reader
.find_latest(&window_created_events, |e| e.id == window.id()) .iter(&window_created_events)
.is_some() .any(|e| e.id == window.id())
|| self || self
.window_resized_event_reader .window_resized_event_reader
.find_latest(&window_resized_events, |e| e.id == window.id()) .iter(&window_resized_events)
.is_some() .any(|e| e.id == window.id())
{ {
render_resource_context.create_swap_chain(window); render_resource_context.create_swap_chain(window);
} }

View File

@ -3,7 +3,7 @@ use crate::{
renderer::{RenderContext, RenderResourceId, RenderResourceType}, renderer::{RenderContext, RenderResourceId, RenderResourceType},
texture::TextureDescriptor, texture::TextureDescriptor,
}; };
use bevy_app::prelude::{EventReader, Events}; use bevy_app::{prelude::Events, ManualEventReader};
use bevy_ecs::{Resources, World}; use bevy_ecs::{Resources, World};
use bevy_window::{WindowCreated, WindowId, WindowResized, Windows}; use bevy_window::{WindowCreated, WindowId, WindowResized, Windows};
use std::borrow::Cow; use std::borrow::Cow;
@ -11,8 +11,8 @@ use std::borrow::Cow;
pub struct WindowTextureNode { pub struct WindowTextureNode {
window_id: WindowId, window_id: WindowId,
descriptor: TextureDescriptor, descriptor: TextureDescriptor,
window_created_event_reader: EventReader<WindowCreated>, window_created_event_reader: ManualEventReader<WindowCreated>,
window_resized_event_reader: EventReader<WindowResized>, window_resized_event_reader: ManualEventReader<WindowResized>,
} }
impl WindowTextureNode { impl WindowTextureNode {
@ -56,12 +56,12 @@ impl Node for WindowTextureNode {
if self if self
.window_created_event_reader .window_created_event_reader
.find_latest(&window_created_events, |e| e.id == window.id()) .iter(&window_created_events)
.is_some() .any(|e| e.id == window.id())
|| self || self
.window_resized_event_reader .window_resized_event_reader
.find_latest(&window_resized_events, |e| e.id == window.id()) .iter(&window_resized_events)
.is_some() .any(|e| e.id == window.id())
{ {
let render_resource_context = render_context.resources_mut(); let render_resource_context = render_context.resources_mut();
if let Some(RenderResourceId::Texture(old_texture)) = output.get(WINDOW_TEXTURE) { if let Some(RenderResourceId::Texture(old_texture)) = output.get(WINDOW_TEXTURE) {

View File

@ -4,9 +4,9 @@ use crate::{
}; };
use super::ShaderLayout; use super::ShaderLayout;
use bevy_app::{EventReader, Events}; use bevy_app::EventReader;
use bevy_asset::{AssetEvent, AssetLoader, Assets, Handle, LoadContext, LoadedAsset}; use bevy_asset::{AssetEvent, AssetLoader, Assets, Handle, LoadContext, LoadedAsset};
use bevy_ecs::{Local, Res, ResMut}; use bevy_ecs::{Res, ResMut};
use bevy_reflect::TypeUuid; use bevy_reflect::TypeUuid;
use bevy_utils::{tracing::error, BoxedFuture}; use bevy_utils::{tracing::error, BoxedFuture};
use std::marker::Copy; use std::marker::Copy;
@ -281,12 +281,11 @@ impl AssetLoader for ShaderLoader {
pub fn shader_update_system( pub fn shader_update_system(
mut shaders: ResMut<Assets<Shader>>, mut shaders: ResMut<Assets<Shader>>,
mut pipelines: ResMut<Assets<PipelineDescriptor>>, mut pipelines: ResMut<Assets<PipelineDescriptor>>,
shader_events: Res<Events<AssetEvent<Shader>>>, mut shader_events: EventReader<AssetEvent<Shader>>,
mut shader_event_reader: Local<EventReader<AssetEvent<Shader>>>,
mut pipeline_compiler: ResMut<PipelineCompiler>, mut pipeline_compiler: ResMut<PipelineCompiler>,
render_resource_context: Res<Box<dyn RenderResourceContext>>, render_resource_context: Res<Box<dyn RenderResourceContext>>,
) { ) {
for event in shader_event_reader.iter(&shader_events) { for event in shader_events.iter() {
match event { match event {
AssetEvent::Modified { handle } => { AssetEvent::Modified { handle } => {
if let Err(e) = pipeline_compiler.update_shader( if let Err(e) = pipeline_compiler.update_shader(

View File

@ -2,9 +2,9 @@ use super::{Extent3d, SamplerDescriptor, TextureDescriptor, TextureDimension, Te
use crate::renderer::{ use crate::renderer::{
RenderResource, RenderResourceContext, RenderResourceId, RenderResourceType, RenderResource, RenderResourceContext, RenderResourceId, RenderResourceType,
}; };
use bevy_app::prelude::{EventReader, Events}; use bevy_app::prelude::EventReader;
use bevy_asset::{AssetEvent, Assets, Handle}; use bevy_asset::{AssetEvent, Assets, Handle};
use bevy_ecs::{Res, ResMut}; use bevy_ecs::Res;
use bevy_reflect::TypeUuid; use bevy_reflect::TypeUuid;
use bevy_utils::HashSet; use bevy_utils::HashSet;
@ -126,14 +126,13 @@ impl Texture {
} }
pub fn texture_resource_system( pub fn texture_resource_system(
mut state: ResMut<TextureResourceSystemState>,
render_resource_context: Res<Box<dyn RenderResourceContext>>, render_resource_context: Res<Box<dyn RenderResourceContext>>,
textures: Res<Assets<Texture>>, textures: Res<Assets<Texture>>,
texture_events: Res<Events<AssetEvent<Texture>>>, mut texture_events: EventReader<AssetEvent<Texture>>,
) { ) {
let render_resource_context = &**render_resource_context; let render_resource_context = &**render_resource_context;
let mut changed_textures = HashSet::default(); let mut changed_textures = HashSet::default();
for event in state.event_reader.iter(&texture_events) { for event in texture_events.iter() {
match event { match event {
AssetEvent::Created { handle } => { AssetEvent::Created { handle } => {
changed_textures.insert(handle); changed_textures.insert(handle);
@ -191,11 +190,6 @@ impl Texture {
} }
} }
#[derive(Default)]
pub struct TextureResourceSystemState {
event_reader: EventReader<AssetEvent<Texture>>,
}
impl RenderResource for Option<Handle<Texture>> { impl RenderResource for Option<Handle<Texture>> {
fn resource_type(&self) -> Option<RenderResourceType> { fn resource_type(&self) -> Option<RenderResourceType> {
self.as_ref().map(|_texture| RenderResourceType::Texture) self.as_ref().map(|_texture| RenderResourceType::Texture)

View File

@ -1,5 +1,5 @@
use crate::{DynamicScene, Scene}; use crate::{DynamicScene, Scene};
use bevy_app::prelude::*; use bevy_app::{prelude::*, ManualEventReader};
use bevy_asset::{AssetEvent, Assets, Handle}; use bevy_asset::{AssetEvent, Assets, Handle};
use bevy_ecs::{Entity, EntityMap, Resources, World}; use bevy_ecs::{Entity, EntityMap, Resources, World};
use bevy_reflect::{ReflectComponent, ReflectMapEntities, TypeRegistryArc}; use bevy_reflect::{ReflectComponent, ReflectMapEntities, TypeRegistryArc};
@ -27,7 +27,7 @@ pub struct SceneSpawner {
spawned_scenes: HashMap<Handle<Scene>, Vec<InstanceId>>, spawned_scenes: HashMap<Handle<Scene>, Vec<InstanceId>>,
spawned_dynamic_scenes: HashMap<Handle<DynamicScene>, Vec<InstanceId>>, spawned_dynamic_scenes: HashMap<Handle<DynamicScene>, Vec<InstanceId>>,
spawned_instances: HashMap<InstanceId, InstanceInfo>, spawned_instances: HashMap<InstanceId, InstanceInfo>,
scene_asset_event_reader: EventReader<AssetEvent<DynamicScene>>, scene_asset_event_reader: ManualEventReader<AssetEvent<DynamicScene>>,
dynamic_scenes_to_spawn: Vec<Handle<DynamicScene>>, dynamic_scenes_to_spawn: Vec<Handle<DynamicScene>>,
scenes_to_spawn: Vec<(Handle<Scene>, InstanceId)>, scenes_to_spawn: Vec<(Handle<Scene>, InstanceId)>,
scenes_to_despawn: Vec<Handle<DynamicScene>>, scenes_to_despawn: Vec<Handle<DynamicScene>>,

View File

@ -1,8 +1,8 @@
mod convert; mod convert;
use crate::{Node, Style}; use crate::{Node, Style};
use bevy_app::{EventReader, Events}; use bevy_app::EventReader;
use bevy_ecs::{Changed, Entity, Flags, Local, Query, QueryFilter, Res, ResMut, With, Without}; use bevy_ecs::{Changed, Entity, Flags, Query, QueryFilter, Res, ResMut, With, Without};
use bevy_log::warn; use bevy_log::warn;
use bevy_math::Vec2; use bevy_math::Vec2;
use bevy_text::CalculatedSize; use bevy_text::CalculatedSize;
@ -187,8 +187,7 @@ unsafe impl Sync for FlexSurface {}
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub fn flex_node_system( pub fn flex_node_system(
windows: Res<Windows>, windows: Res<Windows>,
mut scale_factor_reader: Local<EventReader<WindowScaleFactorChanged>>, mut scale_factor_events: EventReader<WindowScaleFactorChanged>,
scale_factor_events: Res<Events<WindowScaleFactorChanged>>,
mut flex_surface: ResMut<FlexSurface>, mut flex_surface: ResMut<FlexSurface>,
root_node_query: Query<Entity, (With<Node>, Without<Parent>)>, root_node_query: Query<Entity, (With<Node>, Without<Parent>)>,
node_query: Query<(Entity, &Style, Option<&CalculatedSize>), (With<Node>, Changed<Style>)>, node_query: Query<(Entity, &Style, Option<&CalculatedSize>), (With<Node>, Changed<Style>)>,
@ -219,7 +218,7 @@ pub fn flex_node_system(
1. 1.
}; };
if scale_factor_reader.latest(&scale_factor_events).is_some() { if scale_factor_events.iter().next_back().is_some() {
update_changed( update_changed(
&mut *flex_surface, &mut *flex_surface,
logical_to_physical_factor, logical_to_physical_factor,

View File

@ -2,7 +2,7 @@ use crate::{
renderer::{WgpuRenderGraphExecutor, WgpuRenderResourceContext}, renderer::{WgpuRenderGraphExecutor, WgpuRenderResourceContext},
WgpuBackend, WgpuOptions, WgpuPowerOptions, WgpuBackend, WgpuOptions, WgpuPowerOptions,
}; };
use bevy_app::prelude::*; use bevy_app::{prelude::*, ManualEventReader};
use bevy_ecs::{Resources, World}; use bevy_ecs::{Resources, World};
use bevy_render::{ use bevy_render::{
render_graph::{DependentNodeStager, RenderGraph, RenderGraphStager}, render_graph::{DependentNodeStager, RenderGraph, RenderGraphStager},
@ -15,8 +15,8 @@ pub struct WgpuRenderer {
pub instance: wgpu::Instance, pub instance: wgpu::Instance,
pub device: Arc<wgpu::Device>, pub device: Arc<wgpu::Device>,
pub queue: wgpu::Queue, pub queue: wgpu::Queue,
pub window_resized_event_reader: EventReader<WindowResized>, pub window_resized_event_reader: ManualEventReader<WindowResized>,
pub window_created_event_reader: EventReader<WindowCreated>, pub window_created_event_reader: ManualEventReader<WindowCreated>,
pub initialized: bool, pub initialized: bool,
} }

View File

@ -3,24 +3,13 @@ use bevy_app::{
prelude::{EventReader, Events}, prelude::{EventReader, Events},
AppExit, AppExit,
}; };
use bevy_ecs::{Local, Res, ResMut}; use bevy_ecs::ResMut;
#[derive(Default)]
pub struct ExitOnWindowCloseState {
event_reader: EventReader<WindowCloseRequested>,
}
pub fn exit_on_window_close_system( pub fn exit_on_window_close_system(
mut state: Local<ExitOnWindowCloseState>,
mut app_exit_events: ResMut<Events<AppExit>>, mut app_exit_events: ResMut<Events<AppExit>>,
window_close_requested_events: Res<Events<WindowCloseRequested>>, mut window_close_requested_events: EventReader<WindowCloseRequested>,
) { ) {
if state if window_close_requested_events.iter().next().is_some() {
.event_reader
.iter(&window_close_requested_events)
.next()
.is_some()
{
app_exit_events.send(AppExit); app_exit_events.send(AppExit);
} }
} }

View File

@ -10,7 +10,7 @@ use bevy_input::{
pub use winit_config::*; pub use winit_config::*;
pub use winit_windows::*; pub use winit_windows::*;
use bevy_app::{prelude::*, AppExit}; use bevy_app::{prelude::*, AppExit, ManualEventReader};
use bevy_ecs::{IntoSystem, Resources, World}; use bevy_ecs::{IntoSystem, Resources, World};
use bevy_math::Vec2; use bevy_math::Vec2;
use bevy_utils::tracing::{error, trace, warn}; use bevy_utils::tracing::{error, trace, warn};
@ -191,8 +191,8 @@ pub fn winit_runner_any_thread(app: App) {
} }
pub fn winit_runner_with(mut app: App, mut event_loop: EventLoop<()>) { pub fn winit_runner_with(mut app: App, mut event_loop: EventLoop<()>) {
let mut create_window_event_reader = EventReader::<CreateWindow>::default(); let mut create_window_event_reader = ManualEventReader::<CreateWindow>::default();
let mut app_exit_event_reader = EventReader::<AppExit>::default(); let mut app_exit_event_reader = ManualEventReader::<AppExit>::default();
app.resources.insert_thread_local(event_loop.create_proxy()); app.resources.insert_thread_local(event_loop.create_proxy());
@ -209,7 +209,11 @@ pub fn winit_runner_with(mut app: App, mut event_loop: EventLoop<()>) {
*control_flow = ControlFlow::Poll; *control_flow = ControlFlow::Poll;
if let Some(app_exit_events) = app.resources.get_mut::<Events<AppExit>>() { if let Some(app_exit_events) = app.resources.get_mut::<Events<AppExit>>() {
if app_exit_event_reader.latest(&app_exit_events).is_some() { if app_exit_event_reader
.iter(&app_exit_events)
.next_back()
.is_some()
{
*control_flow = ControlFlow::Exit; *control_flow = ControlFlow::Exit;
} }
} }
@ -453,7 +457,7 @@ pub fn winit_runner_with(mut app: App, mut event_loop: EventLoop<()>) {
fn handle_create_window_events( fn handle_create_window_events(
resources: &mut Resources, resources: &mut Resources,
event_loop: &EventLoopWindowTarget<()>, event_loop: &EventLoopWindowTarget<()>,
create_window_event_reader: &mut EventReader<CreateWindow>, create_window_event_reader: &mut ManualEventReader<CreateWindow>,
) { ) {
let mut winit_windows = resources.get_mut::<WinitWindows>().unwrap(); let mut winit_windows = resources.get_mut::<WinitWindows>().unwrap();
let mut windows = resources.get_mut::<Windows>().unwrap(); let mut windows = resources.get_mut::<Windows>().unwrap();

View File

@ -7,11 +7,8 @@ fn main() {
.run(); .run();
} }
fn file_drag_and_drop_system( fn file_drag_and_drop_system(mut events: EventReader<FileDragAndDrop>) {
mut reader: Local<EventReader<FileDragAndDrop>>, for event in events.iter() {
events: Res<Events<FileDragAndDrop>>,
) {
for event in reader.iter(&events) {
println!("{:?}", event); println!("{:?}", event);
} }
} }

View File

@ -42,11 +42,8 @@ fn event_trigger_system(
} }
// prints events as they come in // prints events as they come in
fn event_listener_system( fn event_listener_system(mut events: EventReader<MyEvent>) {
mut my_event_reader: Local<EventReader<MyEvent>>, for my_event in events.iter() {
my_events: Res<Events<MyEvent>>,
) {
for my_event in my_event_reader.iter(&my_events) {
println!("{}", my_event.message); println!("{}", my_event.message);
} }
} }

View File

@ -7,17 +7,9 @@ fn main() {
.run(); .run();
} }
#[derive(Default)]
struct State {
event_reader: EventReader<ReceivedCharacter>,
}
/// This system prints out all char events as they come in /// This system prints out all char events as they come in
fn print_char_event_system( fn print_char_event_system(mut char_input_events: EventReader<ReceivedCharacter>) {
mut state: Local<State>, for event in char_input_events.iter() {
char_input_events: Res<Events<ReceivedCharacter>>,
) {
for event in state.event_reader.iter(&char_input_events) {
println!("{:?}: '{}'", event, event.char); println!("{:?}: '{}'", event, event.char);
} }
} }

View File

@ -16,11 +16,13 @@ fn main() {
#[derive(Default)] #[derive(Default)]
struct GamepadLobby { struct GamepadLobby {
gamepads: HashSet<Gamepad>, gamepads: HashSet<Gamepad>,
gamepad_event_reader: EventReader<GamepadEvent>,
} }
fn connection_system(mut lobby: ResMut<GamepadLobby>, gamepad_event: Res<Events<GamepadEvent>>) { fn connection_system(
for event in lobby.gamepad_event_reader.iter(&gamepad_event) { mut lobby: ResMut<GamepadLobby>,
mut gamepad_event: EventReader<GamepadEvent>,
) {
for event in gamepad_event.iter() {
match &event { match &event {
GamepadEvent(gamepad, GamepadEventType::Connected) => { GamepadEvent(gamepad, GamepadEventType::Connected) => {
lobby.gamepads.insert(*gamepad); lobby.gamepads.insert(*gamepad);

View File

@ -10,11 +10,8 @@ fn main() {
.run(); .run();
} }
fn gamepad_events( fn gamepad_events(mut gamepad_event: EventReader<GamepadEvent>) {
mut event_reader: Local<EventReader<GamepadEvent>>, for event in gamepad_event.iter() {
gamepad_event: Res<Events<GamepadEvent>>,
) {
for event in event_reader.iter(&gamepad_event) {
match &event { match &event {
GamepadEvent(gamepad, GamepadEventType::Connected) => { GamepadEvent(gamepad, GamepadEventType::Connected) => {
println!("{:?} Connected", gamepad); println!("{:?} Connected", gamepad);

View File

@ -7,17 +7,9 @@ fn main() {
.run(); .run();
} }
#[derive(Default)]
struct State {
event_reader: EventReader<KeyboardInput>,
}
/// This system prints out all keyboard events as they come in /// This system prints out all keyboard events as they come in
fn print_keyboard_event_system( fn print_keyboard_event_system(mut keyboard_input_events: EventReader<KeyboardInput>) {
mut state: Local<State>, for event in keyboard_input_events.iter() {
keyboard_input_events: Res<Events<KeyboardInput>>,
) {
for event in state.event_reader.iter(&keyboard_input_events) {
println!("{:?}", event); println!("{:?}", event);
} }
} }

View File

@ -11,38 +11,26 @@ fn main() {
.run(); .run();
} }
#[derive(Default)]
struct State {
mouse_button_event_reader: EventReader<MouseButtonInput>,
mouse_motion_event_reader: EventReader<MouseMotion>,
cursor_moved_event_reader: EventReader<CursorMoved>,
mouse_wheel_event_reader: EventReader<MouseWheel>,
}
/// This system prints out all mouse events as they come in /// This system prints out all mouse events as they come in
fn print_mouse_events_system( fn print_mouse_events_system(
mut state: Local<State>, mut mouse_button_input_events: EventReader<MouseButtonInput>,
mouse_button_input_events: Res<Events<MouseButtonInput>>, mut mouse_motion_events: EventReader<MouseMotion>,
mouse_motion_events: Res<Events<MouseMotion>>, mut cursor_moved_events: EventReader<CursorMoved>,
cursor_moved_events: Res<Events<CursorMoved>>, mut mouse_wheel_events: EventReader<MouseWheel>,
mouse_wheel_events: Res<Events<MouseWheel>>,
) { ) {
for event in state for event in mouse_button_input_events.iter() {
.mouse_button_event_reader
.iter(&mouse_button_input_events)
{
println!("{:?}", event); println!("{:?}", event);
} }
for event in state.mouse_motion_event_reader.iter(&mouse_motion_events) { for event in mouse_motion_events.iter() {
println!("{:?}", event); println!("{:?}", event);
} }
for event in state.cursor_moved_event_reader.iter(&cursor_moved_events) { for event in cursor_moved_events.iter() {
println!("{:?}", event); println!("{:?}", event);
} }
for event in state.mouse_wheel_event_reader.iter(&mouse_wheel_events) { for event in mouse_wheel_events.iter() {
println!("{:?}", event); println!("{:?}", event);
} }
} }

View File

@ -7,13 +7,8 @@ fn main() {
.run(); .run();
} }
#[derive(Default)] fn touch_event_system(mut touch_events: EventReader<TouchInput>) {
struct State { for event in touch_events.iter() {
event_reader: EventReader<TouchInput>,
}
fn touch_event_system(mut state: Local<State>, touch_events: Res<Events<TouchInput>>) {
for event in state.event_reader.iter(&touch_events) {
println!("{:?}", event); println!("{:?}", event);
} }
} }

View File

@ -19,7 +19,6 @@ fn main() {
// Track ticks (sanity check, whether game loop is running) // Track ticks (sanity check, whether game loop is running)
.add_system(counter.system()) .add_system(counter.system())
// Track input events // Track input events
.init_resource::<TrackInputState>()
.add_system(track_input_events.system()) .add_system(track_input_events.system())
.run(); .run();
} }
@ -45,25 +44,15 @@ struct CounterState {
count: u32, count: u32,
} }
#[derive(Default)]
struct TrackInputState {
keys: EventReader<KeyboardInput>,
cursor: EventReader<CursorMoved>,
motion: EventReader<MouseMotion>,
mousebtn: EventReader<MouseButtonInput>,
scroll: EventReader<MouseWheel>,
}
fn track_input_events( fn track_input_events(
mut state: ResMut<TrackInputState>, mut ev_keys: EventReader<KeyboardInput>,
ev_keys: Res<Events<KeyboardInput>>, mut ev_cursor: EventReader<CursorMoved>,
ev_cursor: Res<Events<CursorMoved>>, mut ev_motion: EventReader<MouseMotion>,
ev_motion: Res<Events<MouseMotion>>, mut ev_mousebtn: EventReader<MouseButtonInput>,
ev_mousebtn: Res<Events<MouseButtonInput>>, mut ev_scroll: EventReader<MouseWheel>,
ev_scroll: Res<Events<MouseWheel>>,
) { ) {
// Keyboard input // Keyboard input
for ev in state.keys.iter(&ev_keys) { for ev in ev_keys.iter() {
if ev.state.is_pressed() { if ev.state.is_pressed() {
info!("Just pressed key: {:?}", ev.key_code); info!("Just pressed key: {:?}", ev.key_code);
} else { } else {
@ -72,17 +61,17 @@ fn track_input_events(
} }
// Absolute cursor position (in window coordinates) // Absolute cursor position (in window coordinates)
for ev in state.cursor.iter(&ev_cursor) { for ev in ev_cursor.iter() {
info!("Cursor at: {}", ev.position); info!("Cursor at: {}", ev.position);
} }
// Relative mouse motion // Relative mouse motion
for ev in state.motion.iter(&ev_motion) { for ev in ev_motion.iter() {
info!("Mouse moved {} pixels", ev.delta); info!("Mouse moved {} pixels", ev.delta);
} }
// Mouse buttons // Mouse buttons
for ev in state.mousebtn.iter(&ev_mousebtn) { for ev in ev_mousebtn.iter() {
if ev.state.is_pressed() { if ev.state.is_pressed() {
info!("Just pressed mouse button: {:?}", ev.button); info!("Just pressed mouse button: {:?}", ev.button);
} else { } else {
@ -91,7 +80,7 @@ fn track_input_events(
} }
// scrolling (mouse wheel, touchpad, etc.) // scrolling (mouse wheel, touchpad, etc.)
for ev in state.scroll.iter(&ev_scroll) { for ev in ev_scroll.iter() {
info!( info!(
"Scrolled vertically by {} and horizontally by {}.", "Scrolled vertically by {} and horizontally by {}.",
ev.y, ev.x ev.y, ev.x