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 std::{fmt, marker::PhantomData};
@ -122,141 +122,105 @@ 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.
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,
_marker: PhantomData<T>,
}
impl<T> Default for EventReader<T> {
impl<T> Default for ManualEventReader<T> {
fn default() -> Self {
Self {
ManualEventReader {
last_event_count: 0,
_marker: PhantomData::default(),
_marker: Default::default(),
}
}
}
impl<T> EventReader<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.
impl<T> ManualEventReader<T> {
/// See [`EventReader::iter`]
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>(
&mut self,
events: &'a Events<T>,
) -> impl DoubleEndedIterator<Item = (&'a T, EventId<T>)> {
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<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.
// 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<Item = &T> {
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<Item = (&T, EventId<T>)> {
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<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.
// 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<T>) -> 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<T>) -> Option<(&'a T, EventId<T>)> {
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<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)
})
}
}
impl<T: bevy_ecs::Resource> Events<T> {
@ -278,17 +242,17 @@ impl<T: bevy_ecs::Resource> Events<T> {
self.event_count += 1;
}
/// Gets a new [EventReader]. This will include all events already in the event buffers.
pub fn get_reader(&self) -> EventReader<T> {
EventReader {
/// Gets a new [ManualEventReader]. This will include all events already in the event buffers.
pub fn get_reader(&self) -> ManualEventReader<T> {
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<T> {
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<T> {
ManualEventReader {
last_event_count: self.event_count,
_marker: PhantomData,
}
@ -461,7 +425,7 @@ mod tests {
fn get_events(
events: &Events<TestEvent>,
reader: &mut EventReader<TestEvent>,
reader: &mut ManualEventReader<TestEvent>,
) -> Vec<TestEvent> {
reader.iter(events).cloned().collect::<Vec<TestEvent>>()
}

View File

@ -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::<AppExit>::default();
let mut app_exit_event_reader = ManualEventReader::<AppExit>::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::<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());
}
}
@ -76,7 +73,8 @@ impl Plugin for ScheduleRunnerPlugin {
app.update();
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());
}
}

View File

@ -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);)*

View File

@ -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<EventReader<GamepadEventRaw>>,
mut button_input: ResMut<Input<GamepadButton>>,
mut axis: ResMut<Axis<GamepadAxis>>,
mut button_axis: ResMut<Axis<GamepadButton>>,
raw_events: Res<Events<GamepadEventRaw>>,
mut raw_events: EventReader<GamepadEventRaw>,
mut events: ResMut<Events<GamepadEvent>>,
settings: Res<GamepadSettings>,
) {
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 => {

View File

@ -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<KeyboardInput>,
}
/// Updates the Input<KeyCode> resource with the latest KeyboardInput events
pub fn keyboard_input_system(
mut state: Local<KeyboardInputState>,
mut keyboard_input: ResMut<Input<KeyCode>>,
keyboard_input_events: Res<Events<KeyboardInput>>,
mut keyboard_input_events: EventReader<KeyboardInput>,
) {
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,

View File

@ -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<MouseButtonInput>,
}
/// Updates the Input<MouseButton> resource with the latest MouseButtonInput events
pub fn mouse_button_input_system(
mut state: Local<MouseButtonInputState>,
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();
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),

View File

@ -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<KeyboardInput>,
}
use bevy_ecs::ResMut;
/// Sends the AppExit event whenever the "esc" key is pressed.
pub fn exit_on_esc_system(
mut state: Local<ExitOnEscapeState>,
keyboard_input_events: Res<Events<KeyboardInput>>,
mut keyboard_input_events: EventReader<KeyboardInput>,
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 event.state == ElementState::Pressed && key_code == KeyCode::Escape {
app_exit_events.send(AppExit);

View File

@ -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<TouchInput>,
}
#[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<TouchSystemState>,
mut touch_state: ResMut<Touches>,
touch_input_events: Res<Events<TouchInput>>,
mut touch_input_events: EventReader<TouchInput>,
) {
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);
}
}

View File

@ -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<WindowResized>,
window_created_event_reader: EventReader<WindowCreated>,
}
pub fn camera_system<T: CameraProjection + Component>(
mut state: Local<CameraSystemState>,
window_resized_events: Res<Events<WindowResized>>,
window_created_events: Res<Events<WindowCreated>>,
mut window_resized_events: EventReader<WindowResized>,
mut window_created_events: EventReader<WindowCreated>,
windows: Res<Windows>,
mut queries: QuerySet<(
Query<(Entity, &mut Camera, &mut T)>,
@ -46,11 +39,7 @@ pub fn camera_system<T: CameraProjection + Component>(
) {
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<T: CameraProjection + Component>(
}
// 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;
}

View File

@ -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::<RenderGraph>()
.init_resource::<PipelineCompiler>()
.init_resource::<RenderResourceBindings>()
.init_resource::<TextureResourceSystemState>()
.init_resource::<AssetRenderResourceBindings>()
.init_resource::<ActiveCameras>()
.add_system_to_stage(

View File

@ -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<AssetEvent<Mesh>>,
mesh_entities: HashMap<Handle<Mesh>, MeshEntities>,
}
@ -357,7 +356,7 @@ pub fn mesh_resource_provider_system(
mut state: Local<MeshResourceProviderState>,
render_resource_context: Res<Box<dyn RenderResourceContext>>,
meshes: Res<Assets<Mesh>>,
mesh_events: Res<Events<AssetEvent<Mesh>>>,
mut mesh_events: EventReader<AssetEvent<Mesh>>,
mut queries: QuerySet<(
Query<&mut RenderPipelines, With<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 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());

View File

@ -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<T: Asset> {
event_reader: EventReader<AssetEvent<T>>,
assets_waiting_for_textures: Vec<HandleId>,
_marker: PhantomData<T>,
}
impl<T: Asset> Default for AssetRenderNodeState<T> {
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<T: RenderResources + Asset>(
mut state: Local<RenderResourcesNodeState<HandleId, T>>,
mut asset_state: Local<AssetRenderNodeState<T>>,
assets: Res<Assets<T>>,
asset_events: Res<Events<AssetEvent<T>>>,
mut asset_events: EventReader<AssetEvent<T>>,
mut asset_render_resource_bindings: ResMut<AssetRenderResourceBindings>,
render_resource_context: Res<Box<dyn RenderResourceContext>>,
mut queries: QuerySet<(
@ -632,7 +632,7 @@ fn asset_render_resources_node_system<T: RenderResources + Asset>(
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) {

View File

@ -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<AssetEvent<Texture>>,
pub texture_event_reader: ManualEventReader<AssetEvent<Texture>>,
}
impl Node for TextureCopyNode {

View File

@ -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<WindowCreated>,
window_resized_event_reader: EventReader<WindowResized>,
window_created_event_reader: ManualEventReader<WindowCreated>,
window_resized_event_reader: ManualEventReader<WindowResized>,
}
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);
}

View File

@ -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<WindowCreated>,
window_resized_event_reader: EventReader<WindowResized>,
window_created_event_reader: ManualEventReader<WindowCreated>,
window_resized_event_reader: ManualEventReader<WindowResized>,
}
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) {

View File

@ -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<Assets<Shader>>,
mut pipelines: ResMut<Assets<PipelineDescriptor>>,
shader_events: Res<Events<AssetEvent<Shader>>>,
mut shader_event_reader: Local<EventReader<AssetEvent<Shader>>>,
mut shader_events: EventReader<AssetEvent<Shader>>,
mut pipeline_compiler: ResMut<PipelineCompiler>,
render_resource_context: Res<Box<dyn RenderResourceContext>>,
) {
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(

View File

@ -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<TextureResourceSystemState>,
render_resource_context: Res<Box<dyn RenderResourceContext>>,
textures: Res<Assets<Texture>>,
texture_events: Res<Events<AssetEvent<Texture>>>,
mut texture_events: EventReader<AssetEvent<Texture>>,
) {
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<AssetEvent<Texture>>,
}
impl RenderResource for Option<Handle<Texture>> {
fn resource_type(&self) -> Option<RenderResourceType> {
self.as_ref().map(|_texture| RenderResourceType::Texture)

View File

@ -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<Handle<Scene>, Vec<InstanceId>>,
spawned_dynamic_scenes: HashMap<Handle<DynamicScene>, Vec<InstanceId>>,
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>>,
scenes_to_spawn: Vec<(Handle<Scene>, InstanceId)>,
scenes_to_despawn: Vec<Handle<DynamicScene>>,

View File

@ -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<Windows>,
mut scale_factor_reader: Local<EventReader<WindowScaleFactorChanged>>,
scale_factor_events: Res<Events<WindowScaleFactorChanged>>,
mut scale_factor_events: EventReader<WindowScaleFactorChanged>,
mut flex_surface: ResMut<FlexSurface>,
root_node_query: Query<Entity, (With<Node>, Without<Parent>)>,
node_query: Query<(Entity, &Style, Option<&CalculatedSize>), (With<Node>, Changed<Style>)>,
@ -219,7 +218,7 @@ pub fn flex_node_system(
1.
};
if scale_factor_reader.latest(&scale_factor_events).is_some() {
if scale_factor_events.iter().next_back().is_some() {
update_changed(
&mut *flex_surface,
logical_to_physical_factor,

View File

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

View File

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

View File

@ -10,7 +10,7 @@ use bevy_input::{
pub use winit_config::*;
pub use winit_windows::*;
use bevy_app::{prelude::*, AppExit};
use bevy_app::{prelude::*, AppExit, ManualEventReader};
use bevy_ecs::{IntoSystem, Resources, World};
use bevy_math::Vec2;
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<()>) {
let mut create_window_event_reader = EventReader::<CreateWindow>::default();
let mut app_exit_event_reader = EventReader::<AppExit>::default();
let mut create_window_event_reader = ManualEventReader::<CreateWindow>::default();
let mut app_exit_event_reader = ManualEventReader::<AppExit>::default();
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;
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;
}
}
@ -453,7 +457,7 @@ pub fn winit_runner_with(mut app: App, mut event_loop: EventLoop<()>) {
fn handle_create_window_events(
resources: &mut Resources,
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 windows = resources.get_mut::<Windows>().unwrap();

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -11,38 +11,26 @@ fn main() {
.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
fn print_mouse_events_system(
mut state: Local<State>,
mouse_button_input_events: Res<Events<MouseButtonInput>>,
mouse_motion_events: Res<Events<MouseMotion>>,
cursor_moved_events: Res<Events<CursorMoved>>,
mouse_wheel_events: Res<Events<MouseWheel>>,
mut mouse_button_input_events: EventReader<MouseButtonInput>,
mut mouse_motion_events: EventReader<MouseMotion>,
mut cursor_moved_events: EventReader<CursorMoved>,
mut mouse_wheel_events: EventReader<MouseWheel>,
) {
for event in state
.mouse_button_event_reader
.iter(&mouse_button_input_events)
{
for event in mouse_button_input_events.iter() {
println!("{:?}", event);
}
for event in state.mouse_motion_event_reader.iter(&mouse_motion_events) {
for event in mouse_motion_events.iter() {
println!("{:?}", event);
}
for event in state.cursor_moved_event_reader.iter(&cursor_moved_events) {
for event in cursor_moved_events.iter() {
println!("{:?}", event);
}
for event in state.mouse_wheel_event_reader.iter(&mouse_wheel_events) {
for event in mouse_wheel_events.iter() {
println!("{:?}", event);
}
}

View File

@ -7,13 +7,8 @@ fn main() {
.run();
}
#[derive(Default)]
struct State {
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) {
fn touch_event_system(mut touch_events: EventReader<TouchInput>) {
for event in touch_events.iter() {
println!("{:?}", event);
}
}

View File

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