From a880b5450829411b0248e47cc066915234371d86 Mon Sep 17 00:00:00 2001 From: TheRawMeatball Date: Tue, 19 Jan 2021 09:23:30 +0300 Subject: [PATCH] Make EventReader a SystemParam (#1244) * Add generic support for `#[derive(SystemParam)]` * Make EventReader a SystemParam --- crates/bevy_app/src/event.rs | 208 ++++++++---------- crates/bevy_app/src/schedule_runner.rs | 14 +- crates/bevy_ecs/macros/src/lib.rs | 38 +++- crates/bevy_input/src/gamepad.rs | 7 +- crates/bevy_input/src/keyboard.rs | 16 +- crates/bevy_input/src/mouse.rs | 18 +- crates/bevy_input/src/system.rs | 13 +- crates/bevy_input/src/touch.rs | 14 +- crates/bevy_render/src/camera/camera.rs | 27 +-- crates/bevy_render/src/lib.rs | 2 - crates/bevy_render/src/mesh/mesh.rs | 7 +- .../nodes/render_resources_node.rs | 10 +- .../render_graph/nodes/texture_copy_node.rs | 4 +- .../nodes/window_swapchain_node.rs | 14 +- .../render_graph/nodes/window_texture_node.rs | 14 +- crates/bevy_render/src/shader/shader.rs | 9 +- crates/bevy_render/src/texture/texture.rs | 14 +- crates/bevy_scene/src/scene_spawner.rs | 4 +- crates/bevy_ui/src/flex/mod.rs | 9 +- crates/bevy_wgpu/src/wgpu_renderer.rs | 6 +- crates/bevy_window/src/system.rs | 17 +- crates/bevy_winit/src/lib.rs | 14 +- examples/app/drag_and_drop.rs | 7 +- examples/ecs/event.rs | 7 +- examples/input/char_input_events.rs | 12 +- examples/input/gamepad_input.rs | 8 +- examples/input/gamepad_input_events.rs | 7 +- examples/input/keyboard_input_events.rs | 12 +- examples/input/mouse_input_events.rs | 28 +-- examples/input/touch_input_events.rs | 9 +- examples/wasm/winit_wasm.rs | 31 +-- 31 files changed, 236 insertions(+), 364 deletions(-) diff --git a/crates/bevy_app/src/event.rs b/crates/bevy_app/src/event.rs index 98f9ddafb2..ddc8fd2271 100644 --- a/crates/bevy_app/src/event.rs +++ b/crates/bevy_app/src/event.rs @@ -1,4 +1,4 @@ -use bevy_ecs::ResMut; +use bevy_ecs::{Local, Res, ResMut, SystemParam}; use bevy_utils::tracing::trace; use std::{fmt, marker::PhantomData}; @@ -122,141 +122,105 @@ fn map_instance_event(event_instance: &EventInstance) -> &T { } /// Reads events of type `T` in order and tracks which events have already been read. -pub struct EventReader { +#[derive(SystemParam)] +pub struct EventReader<'a, T: bevy_ecs::Resource> { + last_event_count: Local<'a, (usize, PhantomData)>, + events: Res<'a, Events>, +} + +pub struct ManualEventReader { last_event_count: usize, _marker: PhantomData, } -impl Default for EventReader { +impl Default for ManualEventReader { fn default() -> Self { - Self { + ManualEventReader { last_event_count: 0, - _marker: PhantomData::default(), + _marker: Default::default(), } } } -impl EventReader { - /// 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. +impl ManualEventReader { + /// See [`EventReader::iter`] pub fn iter<'a>(&mut self, events: &'a Events) -> impl DoubleEndedIterator { - 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>( &mut self, events: &'a Events, ) -> impl DoubleEndedIterator)> { - self.iter_internal(events).map(|(event, id)| { + internal_event_reader(&mut self.last_event_count, events) + } +} + +/// Like [`iter_with_id`](EventReader::iter_with_id) except not emitting any traces for read messages. +fn internal_event_reader<'a, T>( + last_event_count: &mut usize, + events: &'a Events, +) -> impl DoubleEndedIterator)> { + // if the reader has seen some of the events in a buffer, find the proper index offset. + // otherwise read all events in the buffer + let a_index = if *last_event_count > events.a_start_event_count { + *last_event_count - events.a_start_event_count + } else { + 0 + }; + let b_index = if *last_event_count > events.b_start_event_count { + *last_event_count - events.b_start_event_count + } else { + 0 + }; + *last_event_count = events.event_count; + match events.state { + State::A => events + .events_b + .get(b_index..) + .unwrap_or_else(|| &[]) + .iter() + .map(map_instance_event_with_id) + .chain( + events + .events_a + .get(a_index..) + .unwrap_or_else(|| &[]) + .iter() + .map(map_instance_event_with_id), + ), + State::B => events + .events_a + .get(a_index..) + .unwrap_or_else(|| &[]) + .iter() + .map(map_instance_event_with_id) + .chain( + events + .events_b + .get(b_index..) + .unwrap_or_else(|| &[]) + .iter() + .map(map_instance_event_with_id), + ), + } +} + +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. + pub fn iter(&mut self) -> impl DoubleEndedIterator { + self.iter_with_id().map(|(event, _id)| event) + } + + /// Like [`iter`](Self::iter), except also returning the [`EventId`] of the events. + pub fn iter_with_id(&mut self) -> impl DoubleEndedIterator)> { + internal_event_reader(&mut self.last_event_count.0, &self.events).map(|(event, id)| { trace!("EventReader::iter() -> {}", id); (event, id) }) } - - /// Like [`iter_with_id`](Self::iter_with_id) except not emitting any traces for read messages. - fn iter_internal<'a>( - &mut self, - events: &'a Events, - ) -> impl DoubleEndedIterator)> { - // if the reader has seen some of the events in a buffer, find the proper index offset. - // otherwise read all events in the buffer - let a_index = if self.last_event_count > events.a_start_event_count { - self.last_event_count - events.a_start_event_count - } else { - 0 - }; - let b_index = if self.last_event_count > events.b_start_event_count { - self.last_event_count - events.b_start_event_count - } else { - 0 - }; - self.last_event_count = events.event_count; - match events.state { - State::A => events - .events_b - .get(b_index..) - .unwrap_or_else(|| &[]) - .iter() - .map(map_instance_event_with_id) - .chain( - events - .events_a - .get(a_index..) - .unwrap_or_else(|| &[]) - .iter() - .map(map_instance_event_with_id), - ), - State::B => events - .events_a - .get(a_index..) - .unwrap_or_else(|| &[]) - .iter() - .map(map_instance_event_with_id) - .chain( - events - .events_b - .get(b_index..) - .unwrap_or_else(|| &[]) - .iter() - .map(map_instance_event_with_id), - ), - } - } - - /// Retrieves the latest event that this EventReader 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 latest<'a>(&mut self, events: &'a Events) -> Option<&'a T> { - self.latest_with_id(events).map(|(event, _)| event) - } - - /// Like [`latest`](Self::latest), except also returning the [`EventId`] of the event. - pub fn latest_with_id<'a>(&mut self, events: &'a Events) -> Option<(&'a T, EventId)> { - self.iter_internal(events).rev().next().map(|(event, id)| { - trace!("EventReader::latest() -> {}", 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, - 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, - mut predicate: impl FnMut(&&T) -> bool, - ) -> Option<(&'a T, EventId)> { - 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) -> 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) -> Option<(&'a T, EventId)> { - self.iter_internal(events).next().map(|(event, id)| { - trace!("EventReader::earliest() -> {}", id); - (event, id) - }) - } } impl Events { @@ -278,17 +242,17 @@ impl Events { self.event_count += 1; } - /// Gets a new [EventReader]. This will include all events already in the event buffers. - pub fn get_reader(&self) -> EventReader { - EventReader { + /// Gets a new [ManualEventReader]. This will include all events already in the event buffers. + pub fn get_reader(&self) -> ManualEventReader { + ManualEventReader { last_event_count: 0, _marker: PhantomData, } } - /// Gets a new [EventReader]. This will ignore all events already in the event buffers. It will read all future events. - pub fn get_reader_current(&self) -> EventReader { - EventReader { + /// 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) -> ManualEventReader { + ManualEventReader { last_event_count: self.event_count, _marker: PhantomData, } @@ -461,7 +425,7 @@ mod tests { fn get_events( events: &Events, - reader: &mut EventReader, + reader: &mut ManualEventReader, ) -> Vec { reader.iter(events).cloned().collect::>() } diff --git a/crates/bevy_app/src/schedule_runner.rs b/crates/bevy_app/src/schedule_runner.rs index c533720406..e3855b2302 100644 --- a/crates/bevy_app/src/schedule_runner.rs +++ b/crates/bevy_app/src/schedule_runner.rs @@ -1,9 +1,5 @@ use super::{App, AppBuilder}; -use crate::{ - app::AppExit, - event::{EventReader, Events}, - plugin::Plugin, -}; +use crate::{app::AppExit, event::Events, plugin::Plugin, ManualEventReader}; use bevy_utils::{Duration, Instant}; #[cfg(target_arch = "wasm32")] @@ -56,7 +52,7 @@ impl Plugin for ScheduleRunnerPlugin { .get_or_insert_with(ScheduleRunnerSettings::default) .to_owned(); app.set_runner(move |mut app: App| { - let mut app_exit_event_reader = EventReader::::default(); + let mut app_exit_event_reader = ManualEventReader::::default(); match settings.run_mode { RunMode::Once => { app.update(); @@ -68,7 +64,8 @@ impl Plugin for ScheduleRunnerPlugin { let start_time = Instant::now(); if let Some(app_exit_events) = app.resources.get_mut::>() { - 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()); } } @@ -76,7 +73,8 @@ impl Plugin for ScheduleRunnerPlugin { app.update(); if let Some(app_exit_events) = app.resources.get_mut::>() { - 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()); } } diff --git a/crates/bevy_ecs/macros/src/lib.rs b/crates/bevy_ecs/macros/src/lib.rs index f860219745..b6984d2a10 100644 --- a/crates/bevy_ecs/macros/src/lib.rs +++ b/crates/bevy_ecs/macros/src/lib.rs @@ -23,8 +23,8 @@ use proc_macro::TokenStream; use proc_macro2::{Span, TokenStream as TokenStream2}; use quote::quote; use syn::{ - parse::ParseStream, parse_macro_input, Data, DataStruct, DeriveInput, Error, Field, Fields, - Ident, Index, Lifetime, Path, Result, + parse::ParseStream, parse_macro_input, punctuated::Punctuated, Data, DataStruct, DeriveInput, + Error, Field, Fields, GenericParam, Ident, Index, Lifetime, Path, Result, Token, }; /// Implement `Bundle` for a monomorphic struct @@ -410,16 +410,44 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream { let generics = ast.generics; 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 fetch_struct_name = Ident::new(&format!("Fetch{}", struct_name), Span::call_site()); 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 { - 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; 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);)* diff --git a/crates/bevy_input/src/gamepad.rs b/crates/bevy_input/src/gamepad.rs index 9106efe872..0f3ce315d3 100644 --- a/crates/bevy_input/src/gamepad.rs +++ b/crates/bevy_input/src/gamepad.rs @@ -1,6 +1,6 @@ use crate::{Axis, Input}; use bevy_app::{EventReader, Events}; -use bevy_ecs::{Local, Res, ResMut}; +use bevy_ecs::{Res, ResMut}; use bevy_utils::HashMap; #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] @@ -202,16 +202,15 @@ impl ButtonAxisSettings { } pub fn gamepad_event_system( - mut event_reader: Local>, mut button_input: ResMut>, mut axis: ResMut>, mut button_axis: ResMut>, - raw_events: Res>, + mut raw_events: EventReader, mut events: ResMut>, settings: Res, ) { button_input.update(); - for event in event_reader.iter(&raw_events) { + for event in raw_events.iter() { let (gamepad, event) = (event.0, &event.1); match event { GamepadEventType::Connected => { diff --git a/crates/bevy_input/src/keyboard.rs b/crates/bevy_input/src/keyboard.rs index 32f6bc4fcd..a113c19155 100644 --- a/crates/bevy_input/src/keyboard.rs +++ b/crates/bevy_input/src/keyboard.rs @@ -1,6 +1,6 @@ use crate::{ElementState, Input}; use bevy_app::prelude::*; -use bevy_ecs::{Local, Res, ResMut}; +use bevy_ecs::ResMut; /// A key input event from a keyboard device #[derive(Debug, Clone)] @@ -10,23 +10,13 @@ pub struct KeyboardInput { pub state: ElementState, } -/// State used by the keyboard input system -#[derive(Default)] -pub struct KeyboardInputState { - keyboard_input_event_reader: EventReader, -} - /// Updates the Input resource with the latest KeyboardInput events pub fn keyboard_input_system( - mut state: Local, mut keyboard_input: ResMut>, - keyboard_input_events: Res>, + mut keyboard_input_events: EventReader, ) { keyboard_input.update(); - for event in state - .keyboard_input_event_reader - .iter(&keyboard_input_events) - { + for event in keyboard_input_events.iter() { if let KeyboardInput { key_code: Some(key_code), state, diff --git a/crates/bevy_input/src/mouse.rs b/crates/bevy_input/src/mouse.rs index f20cfb7331..0d99632c2f 100644 --- a/crates/bevy_input/src/mouse.rs +++ b/crates/bevy_input/src/mouse.rs @@ -1,6 +1,6 @@ use crate::{ElementState, Input}; -use bevy_app::prelude::{EventReader, Events}; -use bevy_ecs::{Local, Res, ResMut}; +use bevy_app::prelude::EventReader; +use bevy_ecs::ResMut; use bevy_math::Vec2; /// A mouse button input event @@ -41,23 +41,13 @@ pub struct MouseWheel { pub y: f32, } -/// State used by the mouse button input system -#[derive(Default)] -pub struct MouseButtonInputState { - mouse_button_input_event_reader: EventReader, -} - /// Updates the Input resource with the latest MouseButtonInput events pub fn mouse_button_input_system( - mut state: Local, mut mouse_button_input: ResMut>, - mouse_button_input_events: Res>, + mut mouse_button_input_events: EventReader, ) { mouse_button_input.update(); - for event in state - .mouse_button_input_event_reader - .iter(&mouse_button_input_events) - { + for event in mouse_button_input_events.iter() { match event.state { ElementState::Pressed => mouse_button_input.press(event.button), ElementState::Released => mouse_button_input.release(event.button), diff --git a/crates/bevy_input/src/system.rs b/crates/bevy_input/src/system.rs index 526c23e67c..d5197ef512 100644 --- a/crates/bevy_input/src/system.rs +++ b/crates/bevy_input/src/system.rs @@ -6,21 +6,14 @@ use bevy_app::{ prelude::{EventReader, Events}, AppExit, }; -use bevy_ecs::{Local, Res, ResMut}; - -/// Local "exit on escape" system state -#[derive(Default)] -pub struct ExitOnEscapeState { - reader: EventReader, -} +use bevy_ecs::ResMut; /// Sends the AppExit event whenever the "esc" key is pressed. pub fn exit_on_esc_system( - mut state: Local, - keyboard_input_events: Res>, + mut keyboard_input_events: EventReader, mut app_exit_events: ResMut>, ) { - 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 event.state == ElementState::Pressed && key_code == KeyCode::Escape { app_exit_events.send(AppExit); diff --git a/crates/bevy_input/src/touch.rs b/crates/bevy_input/src/touch.rs index 31f65d2477..b3b5b90f18 100644 --- a/crates/bevy_input/src/touch.rs +++ b/crates/bevy_input/src/touch.rs @@ -1,5 +1,5 @@ -use bevy_app::{EventReader, Events}; -use bevy_ecs::{Local, Res, ResMut}; +use bevy_app::EventReader; +use bevy_ecs::ResMut; use bevy_math::Vec2; use bevy_utils::HashMap; @@ -77,11 +77,6 @@ pub enum TouchPhase { Cancelled, } -#[derive(Default)] -pub struct TouchSystemState { - touch_event_reader: EventReader, -} - #[derive(Debug, Clone, Copy)] pub struct Touch { id: u64, @@ -226,13 +221,12 @@ impl Touches { /// Updates the Touches resource with the latest TouchInput events pub fn touch_screen_input_system( - mut state: Local, mut touch_state: ResMut, - touch_input_events: Res>, + mut touch_input_events: EventReader, ) { 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); } } diff --git a/crates/bevy_render/src/camera/camera.rs b/crates/bevy_render/src/camera/camera.rs index 22fd64a960..ba1636228c 100644 --- a/crates/bevy_render/src/camera/camera.rs +++ b/crates/bevy_render/src/camera/camera.rs @@ -1,6 +1,6 @@ use super::CameraProjection; -use bevy_app::prelude::{EventReader, Events}; -use bevy_ecs::{Added, Component, Entity, Local, Query, QuerySet, Res}; +use bevy_app::prelude::EventReader; +use bevy_ecs::{Added, Component, Entity, Query, QuerySet, Res}; use bevy_math::Mat4; use bevy_reflect::{Reflect, ReflectComponent}; 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, - window_created_event_reader: EventReader, -} - pub fn camera_system( - mut state: Local, - window_resized_events: Res>, - window_created_events: Res>, + mut window_resized_events: EventReader, + mut window_created_events: EventReader, windows: Res, mut queries: QuerySet<( Query<(Entity, &mut Camera, &mut T)>, @@ -46,11 +39,7 @@ pub fn camera_system( ) { let mut changed_window_ids = Vec::new(); // handle resize events. latest events are handled first because we only want to resize each window once - for event in state - .window_resized_event_reader - .iter(&window_resized_events) - .rev() - { + for event in window_resized_events.iter().rev() { if changed_window_ids.contains(&event.id) { continue; } @@ -59,11 +48,7 @@ pub fn camera_system( } // handle resize events. latest events are handled first because we only want to resize each window once - for event in state - .window_created_event_reader - .iter(&window_created_events) - .rev() - { + for event in window_created_events.iter().rev() { if changed_window_ids.contains(&event.id) { continue; } diff --git a/crates/bevy_render/src/lib.rs b/crates/bevy_render/src/lib.rs index c158d53824..39ca67dc2b 100644 --- a/crates/bevy_render/src/lib.rs +++ b/crates/bevy_render/src/lib.rs @@ -51,7 +51,6 @@ use shader::ShaderLoader; use texture::HdrTextureLoader; #[cfg(feature = "png")] use texture::ImageTextureLoader; -use texture::TextureResourceSystemState; /// The names of "render" App stages pub mod stage { @@ -133,7 +132,6 @@ impl Plugin for RenderPlugin { .init_resource::() .init_resource::() .init_resource::() - .init_resource::() .init_resource::() .init_resource::() .add_system_to_stage( diff --git a/crates/bevy_render/src/mesh/mesh.rs b/crates/bevy_render/src/mesh/mesh.rs index 69c71a1e61..2f68de5b89 100644 --- a/crates/bevy_render/src/mesh/mesh.rs +++ b/crates/bevy_render/src/mesh/mesh.rs @@ -2,7 +2,7 @@ use crate::{ pipeline::{IndexFormat, PrimitiveTopology, RenderPipelines, VertexFormat}, renderer::{BufferInfo, BufferUsage, RenderResourceContext, RenderResourceId}, }; -use bevy_app::prelude::{EventReader, Events}; +use bevy_app::prelude::EventReader; use bevy_asset::{AssetEvent, Assets, Handle}; use bevy_core::AsBytes; use bevy_ecs::{Changed, Entity, Local, Mut, Query, QuerySet, Res, With}; @@ -349,7 +349,6 @@ pub struct MeshEntities { #[derive(Default)] pub struct MeshResourceProviderState { - mesh_event_reader: EventReader>, mesh_entities: HashMap, MeshEntities>, } @@ -357,7 +356,7 @@ pub fn mesh_resource_provider_system( mut state: Local, render_resource_context: Res>, meshes: Res>, - mesh_events: Res>>, + mut mesh_events: EventReader>, mut queries: QuerySet<( Query<&mut RenderPipelines, With>>, Query<(Entity, &Handle, &mut RenderPipelines), Changed>>, @@ -365,7 +364,7 @@ pub fn mesh_resource_provider_system( ) { let mut changed_meshes = HashSet::default(); 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 { AssetEvent::Created { ref handle } => { changed_meshes.insert(handle.clone_weak()); diff --git a/crates/bevy_render/src/render_graph/nodes/render_resources_node.rs b/crates/bevy_render/src/render_graph/nodes/render_resources_node.rs index 0b753e0ba1..68422596b0 100644 --- a/crates/bevy_render/src/render_graph/nodes/render_resources_node.rs +++ b/crates/bevy_render/src/render_graph/nodes/render_resources_node.rs @@ -9,7 +9,7 @@ use crate::{ texture, }; -use bevy_app::{EventReader, Events}; +use bevy_app::EventReader; use bevy_asset::{Asset, AssetEvent, Assets, Handle, HandleId}; use bevy_ecs::{ BoxedSystem, Changed, Commands, Entity, IntoSystem, Local, Or, Query, QuerySet, Res, ResMut, @@ -600,14 +600,14 @@ where } struct AssetRenderNodeState { - event_reader: EventReader>, assets_waiting_for_textures: Vec, + _marker: PhantomData, } impl Default for AssetRenderNodeState { fn default() -> Self { Self { - event_reader: Default::default(), + _marker: Default::default(), assets_waiting_for_textures: Default::default(), } } @@ -618,7 +618,7 @@ fn asset_render_resources_node_system( mut state: Local>, mut asset_state: Local>, assets: Res>, - asset_events: Res>>, + mut asset_events: EventReader>, mut asset_render_resource_bindings: ResMut, render_resource_context: Res>, mut queries: QuerySet<( @@ -632,7 +632,7 @@ fn asset_render_resources_node_system( let render_resource_context = &**render_resource_context; let mut changed_assets = HashMap::default(); - for event in asset_state.event_reader.iter(&asset_events) { + for event in asset_events.iter() { match event { AssetEvent::Created { ref handle } => { if let Some(asset) = assets.get(handle) { diff --git a/crates/bevy_render/src/render_graph/nodes/texture_copy_node.rs b/crates/bevy_render/src/render_graph/nodes/texture_copy_node.rs index 8959a8496d..fcb8bf8015 100644 --- a/crates/bevy_render/src/render_graph/nodes/texture_copy_node.rs +++ b/crates/bevy_render/src/render_graph/nodes/texture_copy_node.rs @@ -3,14 +3,14 @@ use crate::{ renderer::{BufferInfo, BufferUsage, RenderContext}, 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_ecs::{Resources, World}; use bevy_utils::HashSet; #[derive(Default)] pub struct TextureCopyNode { - pub texture_event_reader: EventReader>, + pub texture_event_reader: ManualEventReader>, } impl Node for TextureCopyNode { diff --git a/crates/bevy_render/src/render_graph/nodes/window_swapchain_node.rs b/crates/bevy_render/src/render_graph/nodes/window_swapchain_node.rs index b8a95ccdb9..8347c0a061 100644 --- a/crates/bevy_render/src/render_graph/nodes/window_swapchain_node.rs +++ b/crates/bevy_render/src/render_graph/nodes/window_swapchain_node.rs @@ -2,15 +2,15 @@ use crate::{ render_graph::{Node, ResourceSlotInfo, ResourceSlots}, renderer::{RenderContext, RenderResourceId, RenderResourceType}, }; -use bevy_app::prelude::{EventReader, Events}; +use bevy_app::{prelude::Events, ManualEventReader}; use bevy_ecs::{Resources, World}; use bevy_window::{WindowCreated, WindowId, WindowResized, Windows}; use std::borrow::Cow; pub struct WindowSwapChainNode { window_id: WindowId, - window_created_event_reader: EventReader, - window_resized_event_reader: EventReader, + window_created_event_reader: ManualEventReader, + window_resized_event_reader: ManualEventReader, } impl WindowSwapChainNode { @@ -56,12 +56,12 @@ impl Node for WindowSwapChainNode { // create window swapchain when window is resized or created if self .window_created_event_reader - .find_latest(&window_created_events, |e| e.id == window.id()) - .is_some() + .iter(&window_created_events) + .any(|e| e.id == window.id()) || self .window_resized_event_reader - .find_latest(&window_resized_events, |e| e.id == window.id()) - .is_some() + .iter(&window_resized_events) + .any(|e| e.id == window.id()) { render_resource_context.create_swap_chain(window); } diff --git a/crates/bevy_render/src/render_graph/nodes/window_texture_node.rs b/crates/bevy_render/src/render_graph/nodes/window_texture_node.rs index d287002ab4..ffaee8139d 100644 --- a/crates/bevy_render/src/render_graph/nodes/window_texture_node.rs +++ b/crates/bevy_render/src/render_graph/nodes/window_texture_node.rs @@ -3,7 +3,7 @@ use crate::{ renderer::{RenderContext, RenderResourceId, RenderResourceType}, texture::TextureDescriptor, }; -use bevy_app::prelude::{EventReader, Events}; +use bevy_app::{prelude::Events, ManualEventReader}; use bevy_ecs::{Resources, World}; use bevy_window::{WindowCreated, WindowId, WindowResized, Windows}; use std::borrow::Cow; @@ -11,8 +11,8 @@ use std::borrow::Cow; pub struct WindowTextureNode { window_id: WindowId, descriptor: TextureDescriptor, - window_created_event_reader: EventReader, - window_resized_event_reader: EventReader, + window_created_event_reader: ManualEventReader, + window_resized_event_reader: ManualEventReader, } impl WindowTextureNode { @@ -56,12 +56,12 @@ impl Node for WindowTextureNode { if self .window_created_event_reader - .find_latest(&window_created_events, |e| e.id == window.id()) - .is_some() + .iter(&window_created_events) + .any(|e| e.id == window.id()) || self .window_resized_event_reader - .find_latest(&window_resized_events, |e| e.id == window.id()) - .is_some() + .iter(&window_resized_events) + .any(|e| e.id == window.id()) { let render_resource_context = render_context.resources_mut(); if let Some(RenderResourceId::Texture(old_texture)) = output.get(WINDOW_TEXTURE) { diff --git a/crates/bevy_render/src/shader/shader.rs b/crates/bevy_render/src/shader/shader.rs index d1f2dfde57..1e5098fc63 100644 --- a/crates/bevy_render/src/shader/shader.rs +++ b/crates/bevy_render/src/shader/shader.rs @@ -4,9 +4,9 @@ use crate::{ }; use super::ShaderLayout; -use bevy_app::{EventReader, Events}; +use bevy_app::EventReader; 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_utils::{tracing::error, BoxedFuture}; use std::marker::Copy; @@ -281,12 +281,11 @@ impl AssetLoader for ShaderLoader { pub fn shader_update_system( mut shaders: ResMut>, mut pipelines: ResMut>, - shader_events: Res>>, - mut shader_event_reader: Local>>, + mut shader_events: EventReader>, mut pipeline_compiler: ResMut, render_resource_context: Res>, ) { - for event in shader_event_reader.iter(&shader_events) { + for event in shader_events.iter() { match event { AssetEvent::Modified { handle } => { if let Err(e) = pipeline_compiler.update_shader( diff --git a/crates/bevy_render/src/texture/texture.rs b/crates/bevy_render/src/texture/texture.rs index 89d07ddbdb..dcadaf0d3d 100644 --- a/crates/bevy_render/src/texture/texture.rs +++ b/crates/bevy_render/src/texture/texture.rs @@ -2,9 +2,9 @@ use super::{Extent3d, SamplerDescriptor, TextureDescriptor, TextureDimension, Te use crate::renderer::{ RenderResource, RenderResourceContext, RenderResourceId, RenderResourceType, }; -use bevy_app::prelude::{EventReader, Events}; +use bevy_app::prelude::EventReader; use bevy_asset::{AssetEvent, Assets, Handle}; -use bevy_ecs::{Res, ResMut}; +use bevy_ecs::Res; use bevy_reflect::TypeUuid; use bevy_utils::HashSet; @@ -126,14 +126,13 @@ impl Texture { } pub fn texture_resource_system( - mut state: ResMut, render_resource_context: Res>, textures: Res>, - texture_events: Res>>, + mut texture_events: EventReader>, ) { let render_resource_context = &**render_resource_context; let mut changed_textures = HashSet::default(); - for event in state.event_reader.iter(&texture_events) { + for event in texture_events.iter() { match event { AssetEvent::Created { handle } => { changed_textures.insert(handle); @@ -191,11 +190,6 @@ impl Texture { } } -#[derive(Default)] -pub struct TextureResourceSystemState { - event_reader: EventReader>, -} - impl RenderResource for Option> { fn resource_type(&self) -> Option { self.as_ref().map(|_texture| RenderResourceType::Texture) diff --git a/crates/bevy_scene/src/scene_spawner.rs b/crates/bevy_scene/src/scene_spawner.rs index 794bd2eec2..f3b4710109 100644 --- a/crates/bevy_scene/src/scene_spawner.rs +++ b/crates/bevy_scene/src/scene_spawner.rs @@ -1,5 +1,5 @@ use crate::{DynamicScene, Scene}; -use bevy_app::prelude::*; +use bevy_app::{prelude::*, ManualEventReader}; use bevy_asset::{AssetEvent, Assets, Handle}; use bevy_ecs::{Entity, EntityMap, Resources, World}; use bevy_reflect::{ReflectComponent, ReflectMapEntities, TypeRegistryArc}; @@ -27,7 +27,7 @@ pub struct SceneSpawner { spawned_scenes: HashMap, Vec>, spawned_dynamic_scenes: HashMap, Vec>, spawned_instances: HashMap, - scene_asset_event_reader: EventReader>, + scene_asset_event_reader: ManualEventReader>, dynamic_scenes_to_spawn: Vec>, scenes_to_spawn: Vec<(Handle, InstanceId)>, scenes_to_despawn: Vec>, diff --git a/crates/bevy_ui/src/flex/mod.rs b/crates/bevy_ui/src/flex/mod.rs index 382fde6e4c..b32675534e 100644 --- a/crates/bevy_ui/src/flex/mod.rs +++ b/crates/bevy_ui/src/flex/mod.rs @@ -1,8 +1,8 @@ mod convert; use crate::{Node, Style}; -use bevy_app::{EventReader, Events}; -use bevy_ecs::{Changed, Entity, Flags, Local, Query, QueryFilter, Res, ResMut, With, Without}; +use bevy_app::EventReader; +use bevy_ecs::{Changed, Entity, Flags, Query, QueryFilter, Res, ResMut, With, Without}; use bevy_log::warn; use bevy_math::Vec2; use bevy_text::CalculatedSize; @@ -187,8 +187,7 @@ unsafe impl Sync for FlexSurface {} #[allow(clippy::too_many_arguments)] pub fn flex_node_system( windows: Res, - mut scale_factor_reader: Local>, - scale_factor_events: Res>, + mut scale_factor_events: EventReader, mut flex_surface: ResMut, root_node_query: Query, Without)>, node_query: Query<(Entity, &Style, Option<&CalculatedSize>), (With, Changed