From e6a0f7e9b982893bb2680c5e6128a3af5e9265d5 Mon Sep 17 00:00:00 2001 From: CatThingy Date: Tue, 3 Jan 2023 15:43:49 -0800 Subject: [PATCH 01/16] Remove blanket impl for `Event` --- crates/bevy_ecs/src/event.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/bevy_ecs/src/event.rs b/crates/bevy_ecs/src/event.rs index 0bf642917509b..219c9e4fa09c8 100644 --- a/crates/bevy_ecs/src/event.rs +++ b/crates/bevy_ecs/src/event.rs @@ -10,7 +10,6 @@ use std::{fmt, hash::Hash, iter::Chain, marker::PhantomData, slice::Iter}; /// /// Events must be thread-safe. pub trait Event: Send + Sync + 'static {} -impl Event for T where T: Send + Sync + 'static {} /// An `EventId` uniquely identifies an event. /// From 43f3f38cc3d0f2fc1007e0d0fc5273925ed19531 Mon Sep 17 00:00:00 2001 From: CatThingy Date: Tue, 3 Jan 2023 15:59:29 -0800 Subject: [PATCH 02/16] Add `Event` derive --- crates/bevy_ecs/macros/src/component.rs | 18 ++++++++++++++++++ crates/bevy_ecs/macros/src/lib.rs | 5 +++++ crates/bevy_ecs/src/event.rs | 1 + 3 files changed, 24 insertions(+) diff --git a/crates/bevy_ecs/macros/src/component.rs b/crates/bevy_ecs/macros/src/component.rs index b051e630ebc44..641eca7d04ab5 100644 --- a/crates/bevy_ecs/macros/src/component.rs +++ b/crates/bevy_ecs/macros/src/component.rs @@ -4,6 +4,24 @@ use proc_macro2::{Span, TokenStream as TokenStream2}; use quote::{quote, ToTokens}; use syn::{parse_macro_input, parse_quote, DeriveInput, Error, Ident, Path, Result}; +pub fn derive_event(input: TokenStream) -> TokenStream { + let mut ast = parse_macro_input!(input as DeriveInput); + let bevy_ecs_path: Path = crate::bevy_ecs_path(); + + ast.generics + .make_where_clause() + .predicates + .push(parse_quote! { Self: Send + Sync + 'static }); + + let struct_name = &ast.ident; + let (impl_generics, type_generics, where_clause) = &ast.generics.split_for_impl(); + + TokenStream::from(quote! { + impl #impl_generics #bevy_ecs_path::event::Event for #struct_name #type_generics #where_clause { + } + }) +} + pub fn derive_resource(input: TokenStream) -> TokenStream { let mut ast = parse_macro_input!(input as DeriveInput); let bevy_ecs_path: Path = crate::bevy_ecs_path(); diff --git a/crates/bevy_ecs/macros/src/lib.rs b/crates/bevy_ecs/macros/src/lib.rs index b4dde955dd388..2a1cb69b2304d 100644 --- a/crates/bevy_ecs/macros/src/lib.rs +++ b/crates/bevy_ecs/macros/src/lib.rs @@ -482,6 +482,11 @@ pub(crate) fn bevy_ecs_path() -> syn::Path { BevyManifest::default().get_path("bevy_ecs") } +#[proc_macro_derive(Event)] +pub fn derive_event(input: TokenStream) -> TokenStream { + component::derive_event(input) +} + #[proc_macro_derive(Resource)] pub fn derive_resource(input: TokenStream) -> TokenStream { component::derive_resource(input) diff --git a/crates/bevy_ecs/src/event.rs b/crates/bevy_ecs/src/event.rs index 219c9e4fa09c8..7361d019f40b1 100644 --- a/crates/bevy_ecs/src/event.rs +++ b/crates/bevy_ecs/src/event.rs @@ -5,6 +5,7 @@ use crate::system::{Local, Res, ResMut, Resource, SystemParam}; use bevy_utils::tracing::trace; use std::ops::{Deref, DerefMut}; use std::{fmt, hash::Hash, iter::Chain, marker::PhantomData, slice::Iter}; +pub use bevy_ecs_macros::Event; /// A type that can be stored in an [`Events`] resource /// You can conveniently access events using the [`EventReader`] and [`EventWriter`] system parameter. /// From 36cff61982d3e231d2705c5a0819467a9ec91425 Mon Sep 17 00:00:00 2001 From: CatThingy Date: Tue, 3 Jan 2023 16:10:54 -0800 Subject: [PATCH 03/16] Derive `Event` for events in `bevy_app` --- crates/bevy_app/src/app.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_app/src/app.rs b/crates/bevy_app/src/app.rs index d70669be5a123..f8bf986315ddc 100644 --- a/crates/bevy_app/src/app.rs +++ b/crates/bevy_app/src/app.rs @@ -1009,7 +1009,7 @@ fn run_once(mut app: App) { /// If you don't require access to other components or resources, consider implementing the [`Drop`] /// trait on components/resources for code that runs on exit. That saves you from worrying about /// system schedule ordering, and is idiomatic Rust. -#[derive(Debug, Clone, Default)] +#[derive(Event, Debug, Clone, Default)] pub struct AppExit; #[cfg(test)] From c1b73e994d1fadcb050aa25fa2d32b631da6ad75 Mon Sep 17 00:00:00 2001 From: CatThingy Date: Tue, 3 Jan 2023 16:17:53 -0800 Subject: [PATCH 04/16] Derive `Event` for events in `bevy_hierarchy` --- crates/bevy_hierarchy/src/events.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/bevy_hierarchy/src/events.rs b/crates/bevy_hierarchy/src/events.rs index f68c2a0788a7d..8c8263cecfe74 100644 --- a/crates/bevy_hierarchy/src/events.rs +++ b/crates/bevy_hierarchy/src/events.rs @@ -1,9 +1,9 @@ -use bevy_ecs::prelude::Entity; +use bevy_ecs::{event::Event, prelude::Entity}; /// An [`Event`] that is fired whenever there is a change in the world's hierarchy. /// /// [`Event`]: bevy_ecs::event::Event -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Event, Debug, Clone, PartialEq, Eq)] pub enum HierarchyEvent { /// Fired whenever an [`Entity`] is added as a child to a parent. ChildAdded { From 51eed341f63f47a134fee8470fe3463e84d53686 Mon Sep 17 00:00:00 2001 From: CatThingy Date: Tue, 3 Jan 2023 16:19:22 -0800 Subject: [PATCH 05/16] Derive `Event` for events in `bevy_input` --- crates/bevy_input/src/gamepad.rs | 10 +++++----- crates/bevy_input/src/keyboard.rs | 8 ++++++-- crates/bevy_input/src/mouse.rs | 12 ++++++++---- crates/bevy_input/src/touch.rs | 4 ++-- 4 files changed, 21 insertions(+), 13 deletions(-) diff --git a/crates/bevy_input/src/gamepad.rs b/crates/bevy_input/src/gamepad.rs index 05dd41a02d042..d9d853560ed61 100644 --- a/crates/bevy_input/src/gamepad.rs +++ b/crates/bevy_input/src/gamepad.rs @@ -1,5 +1,5 @@ use crate::{Axis, Input}; -use bevy_ecs::event::{EventReader, EventWriter}; +use bevy_ecs::event::{Event, EventReader, EventWriter}; use bevy_ecs::{ change_detection::DetectChangesMut, system::{Res, ResMut, Resource}, @@ -1037,7 +1037,7 @@ pub enum GamepadConnection { /// A Gamepad connection event. Created when a connection to a gamepad /// is established and when a gamepad is disconnected. -#[derive(Debug, Clone, PartialEq, Reflect, FromReflect)] +#[derive(Event, Debug, Clone, PartialEq, Reflect, FromReflect)] #[reflect(Debug, PartialEq)] #[cfg_attr( feature = "serialize", @@ -1068,7 +1068,7 @@ impl GamepadConnectionEvent { } } -#[derive(Debug, Clone, PartialEq, Reflect, FromReflect)] +#[derive(Event, Debug, Clone, PartialEq, Reflect, FromReflect)] #[reflect(Debug, PartialEq)] #[cfg_attr( feature = "serialize", @@ -1093,7 +1093,7 @@ impl GamepadAxisChangedEvent { /// Gamepad event for when the "value" (amount of pressure) on the button /// changes by an amount larger than the threshold defined in [`GamepadSettings`]. -#[derive(Debug, Clone, PartialEq, Reflect, FromReflect)] +#[derive(Event, Debug, Clone, PartialEq, Reflect, FromReflect)] #[reflect(Debug, PartialEq)] #[cfg_attr( feature = "serialize", @@ -1156,7 +1156,7 @@ pub fn gamepad_button_event_system( /// This event type is used over the [`GamepadConnectionEvent`], /// [`GamepadButtonChangedEvent`] and [`GamepadAxisChangedEvent`] when /// the in-frame relative ordering of events is important. -#[derive(Debug, Clone, PartialEq, Reflect, FromReflect)] +#[derive(Event, Debug, Clone, PartialEq, Reflect, FromReflect)] #[reflect(Debug, PartialEq)] #[cfg_attr( feature = "serialize", diff --git a/crates/bevy_input/src/keyboard.rs b/crates/bevy_input/src/keyboard.rs index a792bc0f4b4df..cc14bac968689 100644 --- a/crates/bevy_input/src/keyboard.rs +++ b/crates/bevy_input/src/keyboard.rs @@ -1,5 +1,9 @@ use crate::{ButtonState, Input}; -use bevy_ecs::{change_detection::DetectChangesMut, event::EventReader, system::ResMut}; +use bevy_ecs::{ + change_detection::DetectChangesMut, + event::{Event, EventReader}, + system::ResMut, +}; use bevy_reflect::{FromReflect, Reflect}; #[cfg(feature = "serialize")] @@ -14,7 +18,7 @@ use bevy_reflect::{ReflectDeserialize, ReflectSerialize}; /// /// The event is consumed inside of the [`keyboard_input_system`](crate::keyboard::keyboard_input_system) /// to update the [`Input`](crate::Input) resource. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Reflect, FromReflect)] +#[derive(Event, Debug, Clone, Copy, PartialEq, Eq, Reflect, FromReflect)] #[reflect(Debug, PartialEq)] #[cfg_attr( feature = "serialize", diff --git a/crates/bevy_input/src/mouse.rs b/crates/bevy_input/src/mouse.rs index 9fbac1ce937ff..5cc81cdcd9faf 100644 --- a/crates/bevy_input/src/mouse.rs +++ b/crates/bevy_input/src/mouse.rs @@ -1,5 +1,9 @@ use crate::{ButtonState, Input}; -use bevy_ecs::{change_detection::DetectChangesMut, event::EventReader, system::ResMut}; +use bevy_ecs::{ + change_detection::DetectChangesMut, + event::{Event, EventReader}, + system::ResMut, +}; use bevy_math::Vec2; use bevy_reflect::{FromReflect, Reflect}; @@ -14,7 +18,7 @@ use bevy_reflect::{ReflectDeserialize, ReflectSerialize}; /// /// The event is read inside of the [`mouse_button_input_system`](crate::mouse::mouse_button_input_system) /// to update the [`Input`](crate::Input) resource. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Reflect, FromReflect)] +#[derive(Event, Debug, Clone, Copy, PartialEq, Eq, Reflect, FromReflect)] #[reflect(Debug, PartialEq)] #[cfg_attr( feature = "serialize", @@ -65,7 +69,7 @@ pub enum MouseButton { /// However, the event data does not make it possible to distinguish which device it is referring to. /// /// [`DeviceEvent::MouseMotion`]: https://docs.rs/winit/latest/winit/event/enum.DeviceEvent.html#variant.MouseMotion -#[derive(Debug, Clone, Copy, PartialEq, Reflect, FromReflect)] +#[derive(Event, Debug, Clone, Copy, PartialEq, Reflect, FromReflect)] #[reflect(Debug, PartialEq)] #[cfg_attr( feature = "serialize", @@ -106,7 +110,7 @@ pub enum MouseScrollUnit { /// A mouse wheel event. /// /// This event is the translated version of the `WindowEvent::MouseWheel` from the `winit` crate. -#[derive(Debug, Clone, Copy, PartialEq, Reflect, FromReflect)] +#[derive(Event, Debug, Clone, Copy, PartialEq, Reflect, FromReflect)] #[reflect(Debug, PartialEq)] #[cfg_attr( feature = "serialize", diff --git a/crates/bevy_input/src/touch.rs b/crates/bevy_input/src/touch.rs index 3f00d994fd3f0..a2b142b9c3887 100644 --- a/crates/bevy_input/src/touch.rs +++ b/crates/bevy_input/src/touch.rs @@ -1,4 +1,4 @@ -use bevy_ecs::event::EventReader; +use bevy_ecs::event::{Event, EventReader}; use bevy_ecs::system::{ResMut, Resource}; use bevy_math::Vec2; use bevy_reflect::{FromReflect, Reflect}; @@ -30,7 +30,7 @@ use bevy_reflect::{ReflectDeserialize, ReflectSerialize}; /// /// This event is the translated version of the `WindowEvent::Touch` from the `winit` crate. /// It is available to the end user and can be used for game logic. -#[derive(Debug, Clone, Copy, PartialEq, Reflect, FromReflect)] +#[derive(Event, Debug, Clone, Copy, PartialEq, Reflect, FromReflect)] #[reflect(Debug, PartialEq)] #[cfg_attr( feature = "serialize", From c9433d34200cdb0f1bceeee35241a04fe8f91165 Mon Sep 17 00:00:00 2001 From: CatThingy Date: Tue, 3 Jan 2023 16:19:35 -0800 Subject: [PATCH 06/16] Derive `Event` for events in `bevy_asset` --- crates/bevy_asset/src/assets.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/bevy_asset/src/assets.rs b/crates/bevy_asset/src/assets.rs index f0f1a035f6617..6417b9fdd3fb8 100644 --- a/crates/bevy_asset/src/assets.rs +++ b/crates/bevy_asset/src/assets.rs @@ -13,6 +13,7 @@ use std::fmt::Debug; /// /// Events sent via the [`Assets`] struct will always be sent with a _Weak_ handle, because the /// asset may not exist by the time the event is handled. +#[derive(Event)] pub enum AssetEvent { #[allow(missing_docs)] Created { handle: Handle }, From 482a287c2cf805bae907365127781edb6916df21 Mon Sep 17 00:00:00 2001 From: CatThingy Date: Tue, 3 Jan 2023 16:19:49 -0800 Subject: [PATCH 07/16] Derive `Event` for events in `bevy_window` --- crates/bevy_window/src/event.rs | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/crates/bevy_window/src/event.rs b/crates/bevy_window/src/event.rs index 955a1edf2dc2b..b26584f296ccd 100644 --- a/crates/bevy_window/src/event.rs +++ b/crates/bevy_window/src/event.rs @@ -1,6 +1,7 @@ use std::path::PathBuf; use bevy_ecs::entity::Entity; +use bevy_ecs::event::Event; use bevy_math::{IVec2, Vec2}; use bevy_reflect::{FromReflect, Reflect}; @@ -8,7 +9,7 @@ use bevy_reflect::{FromReflect, Reflect}; use bevy_reflect::{ReflectDeserialize, ReflectSerialize}; /// A window event that is sent whenever a window's logical size has changed. -#[derive(Debug, Clone, PartialEq, Reflect, FromReflect)] +#[derive(Event, Debug, Clone, PartialEq, Reflect, FromReflect)] #[reflect(Debug, PartialEq)] #[cfg_attr( feature = "serialize", @@ -27,7 +28,7 @@ pub struct WindowResized { // TODO: This would redraw all windows ? If yes, update docs to reflect this /// An event that indicates the window should redraw, even if its control flow is set to `Wait` and /// there have been no window events. -#[derive(Debug, Clone, PartialEq, Eq, Reflect, FromReflect)] +#[derive(Event, Debug, Clone, PartialEq, Eq, Reflect, FromReflect)] #[reflect(Debug, PartialEq)] #[cfg_attr( feature = "serialize", @@ -39,7 +40,7 @@ pub struct RequestRedraw; /// An event that is sent whenever a new window is created. /// /// To create a new window, spawn an entity with a [`crate::Window`] on it. -#[derive(Debug, Clone, PartialEq, Eq, Reflect, FromReflect)] +#[derive(Event, Debug, Clone, PartialEq, Eq, Reflect, FromReflect)] #[reflect(Debug, PartialEq)] #[cfg_attr( feature = "serialize", @@ -61,7 +62,7 @@ pub struct WindowCreated { /// /// [`WindowPlugin`]: crate::WindowPlugin /// [`Window`]: crate::Window -#[derive(Debug, Clone, PartialEq, Eq, Reflect, FromReflect)] +#[derive(Event, Debug, Clone, PartialEq, Eq, Reflect, FromReflect)] #[reflect(Debug, PartialEq)] #[cfg_attr( feature = "serialize", @@ -75,7 +76,7 @@ pub struct WindowCloseRequested { /// An event that is sent whenever a window is closed. This will be sent when /// the window entity loses its `Window` component or is despawned. -#[derive(Debug, Clone, PartialEq, Eq, Reflect, FromReflect)] +#[derive(Event, Debug, Clone, PartialEq, Eq, Reflect, FromReflect)] #[reflect(Debug, PartialEq)] #[cfg_attr( feature = "serialize", @@ -98,7 +99,7 @@ pub struct WindowClosed { /// /// [`WindowEvent::CursorMoved`]: https://docs.rs/winit/latest/winit/event/enum.WindowEvent.html#variant.CursorMoved /// [`MouseMotion`]: bevy_input::mouse::MouseMotion -#[derive(Debug, Clone, PartialEq, Reflect, FromReflect)] +#[derive(Event, Debug, Clone, PartialEq, Reflect, FromReflect)] #[reflect(Debug, PartialEq)] #[cfg_attr( feature = "serialize", @@ -113,7 +114,7 @@ pub struct CursorMoved { } /// An event that is sent whenever the user's cursor enters a window. -#[derive(Debug, Clone, PartialEq, Eq, Reflect, FromReflect)] +#[derive(Event, Debug, Clone, PartialEq, Eq, Reflect, FromReflect)] #[reflect(Debug, PartialEq)] #[cfg_attr( feature = "serialize", @@ -126,7 +127,7 @@ pub struct CursorEntered { } /// An event that is sent whenever the user's cursor leaves a window. -#[derive(Debug, Clone, PartialEq, Eq, Reflect, FromReflect)] +#[derive(Event, Debug, Clone, PartialEq, Eq, Reflect, FromReflect)] #[reflect(Debug, PartialEq)] #[cfg_attr( feature = "serialize", @@ -139,7 +140,7 @@ pub struct CursorLeft { } /// An event that is sent whenever a window receives a character from the OS or underlying system. -#[derive(Debug, Clone, PartialEq, Eq, Reflect, FromReflect)] +#[derive(Event, Debug, Clone, PartialEq, Eq, Reflect, FromReflect)] #[reflect(Debug, PartialEq)] #[cfg_attr( feature = "serialize", @@ -158,7 +159,7 @@ pub struct ReceivedCharacter { /// This event is the translated version of the `WindowEvent::Ime` from the `winit` crate. /// /// It is only sent if IME was enabled on the window with [`Window::ime_enabled`](crate::window::Window::ime_enabled). -#[derive(Debug, Clone, PartialEq, Eq, Reflect, FromReflect)] +#[derive(Event, Debug, Clone, PartialEq, Eq, Reflect, FromReflect)] #[reflect(Debug, PartialEq)] #[cfg_attr( feature = "serialize", @@ -200,7 +201,7 @@ pub enum Ime { } /// An event that indicates a window has received or lost focus. -#[derive(Debug, Clone, PartialEq, Eq, Reflect, FromReflect)] +#[derive(Event, Debug, Clone, PartialEq, Eq, Reflect, FromReflect)] #[reflect(Debug, PartialEq)] #[cfg_attr( feature = "serialize", @@ -215,7 +216,7 @@ pub struct WindowFocused { } /// An event that indicates a window's scale factor has changed. -#[derive(Debug, Clone, PartialEq, Reflect, FromReflect)] +#[derive(Event, Debug, Clone, PartialEq, Reflect, FromReflect)] #[reflect(Debug, PartialEq)] #[cfg_attr( feature = "serialize", @@ -230,7 +231,7 @@ pub struct WindowScaleFactorChanged { } /// An event that indicates a window's OS-reported scale factor has changed. -#[derive(Debug, Clone, PartialEq, Reflect, FromReflect)] +#[derive(Event, Debug, Clone, PartialEq, Reflect, FromReflect)] #[reflect(Debug, PartialEq)] #[cfg_attr( feature = "serialize", @@ -245,7 +246,7 @@ pub struct WindowBackendScaleFactorChanged { } /// Events related to files being dragged and dropped on a window. -#[derive(Debug, Clone, PartialEq, Eq, Reflect, FromReflect)] +#[derive(Event, Debug, Clone, PartialEq, Eq, Reflect, FromReflect)] #[reflect(Debug, PartialEq)] #[cfg_attr( feature = "serialize", @@ -277,7 +278,7 @@ pub enum FileDragAndDrop { } /// An event that is sent when a window is repositioned in physical pixels. -#[derive(Debug, Clone, PartialEq, Eq, Reflect, FromReflect)] +#[derive(Event, Debug, Clone, PartialEq, Eq, Reflect, FromReflect)] #[reflect(Debug, PartialEq)] #[cfg_attr( feature = "serialize", From 673fa4a15fb1ba919368f6bbfad7c78d01c9304d Mon Sep 17 00:00:00 2001 From: CatThingy Date: Tue, 3 Jan 2023 16:32:37 -0800 Subject: [PATCH 08/16] Derive `Event` for events in `bevy_ecs` tests and examples --- crates/bevy_ecs/examples/events.rs | 1 + crates/bevy_ecs/src/event.rs | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/crates/bevy_ecs/examples/events.rs b/crates/bevy_ecs/examples/events.rs index b0f96e39a1421..0e857b797e408 100644 --- a/crates/bevy_ecs/examples/events.rs +++ b/crates/bevy_ecs/examples/events.rs @@ -30,6 +30,7 @@ fn main() { } // This is our event that we will send and receive in systems +#[derive(Event)] struct MyEvent { pub message: String, pub random_value: f32, diff --git a/crates/bevy_ecs/src/event.rs b/crates/bevy_ecs/src/event.rs index 7361d019f40b1..ecc8d05fd32da 100644 --- a/crates/bevy_ecs/src/event.rs +++ b/crates/bevy_ecs/src/event.rs @@ -671,7 +671,7 @@ mod tests { use super::*; - #[derive(Copy, Clone, PartialEq, Eq, Debug)] + #[derive(Event, Copy, Clone, PartialEq, Eq, Debug)] struct TestEvent { i: usize, } @@ -774,7 +774,7 @@ mod tests { reader.iter(events).cloned().collect::>() } - #[derive(PartialEq, Eq, Debug)] + #[derive(Event, PartialEq, Eq, Debug)] struct E(usize); fn events_clear_and_read_impl(clear_func: impl FnOnce(&mut Events)) { @@ -981,7 +981,7 @@ mod tests { assert!(last.is_none(), "EventReader should be empty"); } - #[derive(Clone, PartialEq, Debug, Default)] + #[derive(Event, Clone, PartialEq, Debug, Default)] struct EmptyTestEvent; #[test] From a58f46c7aaa80a01dc46fa18f1aa8c81d957d617 Mon Sep 17 00:00:00 2001 From: CatThingy Date: Tue, 3 Jan 2023 16:35:16 -0800 Subject: [PATCH 09/16] Derive `Event` for events in `bevy` tests and examples --- examples/async_tasks/external_source_external_thread.rs | 2 ++ examples/ecs/event.rs | 3 ++- examples/games/breakout.rs | 2 +- tests/how_to_test_systems.rs | 1 + 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/examples/async_tasks/external_source_external_thread.rs b/examples/async_tasks/external_source_external_thread.rs index 3a174713904fa..9c2cfc646dca9 100644 --- a/examples/async_tasks/external_source_external_thread.rs +++ b/examples/async_tasks/external_source_external_thread.rs @@ -19,6 +19,8 @@ fn main() { #[derive(Resource, Deref)] struct StreamReceiver(Receiver); + +#[derive(Event)] struct StreamEvent(u32); #[derive(Resource, Deref)] diff --git a/examples/ecs/event.rs b/examples/ecs/event.rs index cc4c2a7762de1..b6bb48311a37e 100644 --- a/examples/ecs/event.rs +++ b/examples/ecs/event.rs @@ -15,11 +15,12 @@ fn main() { .run(); } +#[derive(Event)] struct MyEvent { pub message: String, } -#[derive(Default)] +#[derive(Event, Default)] struct PlaySound; #[derive(Resource)] diff --git a/examples/games/breakout.rs b/examples/games/breakout.rs index bc308797fb3e5..0d34e076fca2a 100644 --- a/examples/games/breakout.rs +++ b/examples/games/breakout.rs @@ -88,7 +88,7 @@ struct Velocity(Vec2); #[derive(Component)] struct Collider; -#[derive(Default)] +#[derive(Event, Default)] struct CollisionEvent; #[derive(Component)] diff --git a/tests/how_to_test_systems.rs b/tests/how_to_test_systems.rs index 5e43c8ac2fc58..c7e42b46a131c 100644 --- a/tests/how_to_test_systems.rs +++ b/tests/how_to_test_systems.rs @@ -6,6 +6,7 @@ struct Enemy { score_value: u32, } +#[derive(Event)] struct EnemyDied(u32); #[derive(Resource)] From 10264b8c26c6f484d819a7d065bc6cb8c200772d Mon Sep 17 00:00:00 2001 From: CatThingy Date: Tue, 3 Jan 2023 17:17:19 -0800 Subject: [PATCH 10/16] Derive `Event` for events in `bevy_ecs` doctests --- crates/bevy_ecs/README.md | 1 + crates/bevy_ecs/src/event.rs | 8 ++++++-- crates/bevy_ecs/src/system/function_system.rs | 2 ++ crates/bevy_ecs/src/system/system_param.rs | 1 + 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/crates/bevy_ecs/README.md b/crates/bevy_ecs/README.md index ee9126e1b5fb7..ce5920ee0b62b 100644 --- a/crates/bevy_ecs/README.md +++ b/crates/bevy_ecs/README.md @@ -286,6 +286,7 @@ Events offer a communication channel between one or more systems. Events can be ```rust use bevy_ecs::prelude::*; +#[derive(Event)] struct MyEvent { message: String, } diff --git a/crates/bevy_ecs/src/event.rs b/crates/bevy_ecs/src/event.rs index ecc8d05fd32da..fd1bc853f835c 100644 --- a/crates/bevy_ecs/src/event.rs +++ b/crates/bevy_ecs/src/event.rs @@ -77,8 +77,9 @@ struct EventInstance { /// /// # Example /// ``` -/// use bevy_ecs::event::Events; +/// use bevy_ecs::event::{Event, Events}; /// +/// #[derive(Event)] /// struct MyEvent { /// value: usize /// } @@ -216,6 +217,8 @@ impl<'w, 's, E: Event> EventReader<'w, 's, E> { /// /// ``` /// # use bevy_ecs::prelude::*; + /// # + /// #[derive(Event)] /// struct CollisionEvent; /// /// fn play_collision_sound(mut events: EventReader) { @@ -257,6 +260,7 @@ impl<'a, 'w, 's, E: Event> IntoIterator for &'a mut EventReader<'w, 's, E> { /// ``` /// # use bevy_ecs::prelude::*; /// +/// #[derive(Event)] /// pub struct MyEvent; // Custom event type. /// fn my_system(mut writer: EventWriter) { /// writer.send(MyEvent); @@ -273,7 +277,7 @@ impl<'a, 'w, 's, E: Event> IntoIterator for &'a mut EventReader<'w, 's, E> { /// /// ``` /// # use bevy_ecs::{prelude::*, event::Events}; -/// +/// # #[derive(Event)] /// # pub struct MyEvent; /// fn send_untyped(mut commands: Commands) { /// // Send an event of a specific type without having to declare that diff --git a/crates/bevy_ecs/src/system/function_system.rs b/crates/bevy_ecs/src/system/function_system.rs index fe6701df605c2..f45257dd0506f 100644 --- a/crates/bevy_ecs/src/system/function_system.rs +++ b/crates/bevy_ecs/src/system/function_system.rs @@ -86,6 +86,7 @@ impl SystemMeta { /// use bevy_ecs::{system::SystemState}; /// use bevy_ecs::event::Events; /// +/// #[derive(Event)] /// struct MyEvent; /// #[derive(Resource)] /// struct MyResource(u32); @@ -118,6 +119,7 @@ impl SystemMeta { /// use bevy_ecs::{system::SystemState}; /// use bevy_ecs::event::Events; /// +/// #[derive(Event)] /// struct MyEvent; /// #[derive(Resource)] /// struct CachedSystemState { diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs index 437a726f4413d..34c8cad55687b 100644 --- a/crates/bevy_ecs/src/system/system_param.rs +++ b/crates/bevy_ecs/src/system/system_param.rs @@ -340,6 +340,7 @@ fn assert_component_access_compatibility( /// ``` /// # use bevy_ecs::prelude::*; /// # +/// # #[derive(Event)] /// # struct MyEvent; /// # impl MyEvent { /// # pub fn new() -> Self { Self } From c969487ce664fe51f3aa567b0359d21f929bf0b6 Mon Sep 17 00:00:00 2001 From: CatThingy Date: Tue, 3 Jan 2023 17:17:53 -0800 Subject: [PATCH 11/16] Derive `Event` for events in `bevy_app` doctests --- crates/bevy_app/src/app.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/bevy_app/src/app.rs b/crates/bevy_app/src/app.rs index f8bf986315ddc..0e8a97022b6fc 100644 --- a/crates/bevy_app/src/app.rs +++ b/crates/bevy_app/src/app.rs @@ -570,6 +570,7 @@ impl App { /// # use bevy_app::prelude::*; /// # use bevy_ecs::prelude::*; /// # + /// # #[derive(Event)] /// # struct MyEvent; /// # let mut app = App::new(); /// # From 2a3ca3e57be710f327bdca19b8508a2e6a4eaa6f Mon Sep 17 00:00:00 2001 From: CatThingy Date: Sun, 5 Feb 2023 13:29:10 -0800 Subject: [PATCH 12/16] Derive `Event` for `RemovedComponentEntity` --- crates/bevy_ecs/src/removal_detection.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/bevy_ecs/src/removal_detection.rs b/crates/bevy_ecs/src/removal_detection.rs index 004f08ca347e7..b90435f289c52 100644 --- a/crates/bevy_ecs/src/removal_detection.rs +++ b/crates/bevy_ecs/src/removal_detection.rs @@ -4,7 +4,7 @@ use crate::{ self as bevy_ecs, component::{Component, ComponentId, ComponentIdFor}, entity::Entity, - event::{EventId, Events, ManualEventIterator, ManualEventIteratorWithId, ManualEventReader}, + event::{Event, EventId, Events, ManualEventIterator, ManualEventIteratorWithId, ManualEventReader}, prelude::Local, storage::SparseSet, system::{ReadOnlySystemParam, SystemMeta, SystemParam}, @@ -21,7 +21,7 @@ use std::{ /// Wrapper around [`Entity`] for [`RemovedComponents`]. /// Internally, `RemovedComponents` uses these as an `Events`. -#[derive(Debug, Clone)] +#[derive(Event, Debug, Clone)] pub struct RemovedComponentEntity(Entity); impl From for Entity { From 874bf044ef274fe2ab627962427b07b53a074bc4 Mon Sep 17 00:00:00 2001 From: CatThingy Date: Mon, 6 Feb 2023 09:01:58 -0800 Subject: [PATCH 13/16] formatting --- crates/bevy_ecs/src/event.rs | 2 +- crates/bevy_ecs/src/removal_detection.rs | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/crates/bevy_ecs/src/event.rs b/crates/bevy_ecs/src/event.rs index fd1bc853f835c..46cd3e8c49241 100644 --- a/crates/bevy_ecs/src/event.rs +++ b/crates/bevy_ecs/src/event.rs @@ -2,10 +2,10 @@ use crate as bevy_ecs; use crate::system::{Local, Res, ResMut, Resource, SystemParam}; +pub use bevy_ecs_macros::Event; use bevy_utils::tracing::trace; use std::ops::{Deref, DerefMut}; use std::{fmt, hash::Hash, iter::Chain, marker::PhantomData, slice::Iter}; -pub use bevy_ecs_macros::Event; /// A type that can be stored in an [`Events`] resource /// You can conveniently access events using the [`EventReader`] and [`EventWriter`] system parameter. /// diff --git a/crates/bevy_ecs/src/removal_detection.rs b/crates/bevy_ecs/src/removal_detection.rs index b90435f289c52..6eb1c4d15a41c 100644 --- a/crates/bevy_ecs/src/removal_detection.rs +++ b/crates/bevy_ecs/src/removal_detection.rs @@ -4,7 +4,9 @@ use crate::{ self as bevy_ecs, component::{Component, ComponentId, ComponentIdFor}, entity::Entity, - event::{Event, EventId, Events, ManualEventIterator, ManualEventIteratorWithId, ManualEventReader}, + event::{ + Event, EventId, Events, ManualEventIterator, ManualEventIteratorWithId, ManualEventReader, + }, prelude::Local, storage::SparseSet, system::{ReadOnlySystemParam, SystemMeta, SystemParam}, From 105f6c4941b0c3c72605472c934b2715d0869c7a Mon Sep 17 00:00:00 2001 From: CatThingy Date: Mon, 6 Mar 2023 11:12:01 -0800 Subject: [PATCH 14/16] Add wrapper for `ActionRequest` event in `bevy_a11y` --- crates/bevy_a11y/src/lib.rs | 6 +++++- crates/bevy_winit/src/accessibility.rs | 10 +++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/crates/bevy_a11y/src/lib.rs b/crates/bevy_a11y/src/lib.rs index ed91fe26e0415..73b5c00cba9db 100644 --- a/crates/bevy_a11y/src/lib.rs +++ b/crates/bevy_a11y/src/lib.rs @@ -13,10 +13,14 @@ use accesskit::{NodeBuilder, NodeId}; use bevy_app::Plugin; use bevy_derive::{Deref, DerefMut}; use bevy_ecs::{ - prelude::{Component, Entity}, + prelude::{Component, Entity, Event}, system::Resource, }; +/// Wrapper struct for [`accesskit::ActionRequest`]. Required to allow it to be used as an `Event`. +#[derive(Event, Deref, DerefMut)] +pub struct ActionRequest(pub accesskit::ActionRequest); + /// Resource that tracks whether an assistive technology has requested /// accessibility information. /// diff --git a/crates/bevy_winit/src/accessibility.rs b/crates/bevy_winit/src/accessibility.rs index fd0f4dc1e4645..c9eb0787d8654 100644 --- a/crates/bevy_winit/src/accessibility.rs +++ b/crates/bevy_winit/src/accessibility.rs @@ -4,6 +4,7 @@ use std::{ }; use accesskit_winit::Adapter; +use bevy_a11y::ActionRequest as ActionRequestWrapper; use bevy_a11y::{ accesskit::{ActionHandler, ActionRequest, NodeBuilder, NodeClassSet, Role, TreeUpdate}, AccessKitEntityExt, AccessibilityNode, AccessibilityRequested, Focus, @@ -71,11 +72,14 @@ fn window_closed( } } -fn poll_receivers(handlers: Res, mut actions: EventWriter) { +fn poll_receivers( + handlers: Res, + mut actions: EventWriter, +) { for (_id, handler) in handlers.iter() { let mut handler = handler.lock().unwrap(); while let Some(event) = handler.pop_front() { - actions.send(event); + actions.send(ActionRequestWrapper(event)); } } } @@ -162,7 +166,7 @@ impl Plugin for AccessibilityPlugin { fn build(&self, app: &mut App) { app.init_non_send_resource::() .init_resource::() - .add_event::() + .add_event::() .add_system(handle_window_focus) .add_system(window_closed) .add_system(poll_receivers) From 794bdedbf4e734339e34a9dca5294b924e962c72 Mon Sep 17 00:00:00 2001 From: CatThingy Date: Mon, 5 Jun 2023 18:13:12 -0700 Subject: [PATCH 15/16] Derive `Event` as needed --- benches/benches/bevy_ecs/events/iter.rs | 7 +++++-- benches/benches/bevy_ecs/events/send.rs | 18 ++++++++++++++---- crates/bevy_ecs/src/schedule/condition.rs | 7 ++++++- crates/bevy_input/src/gamepad.rs | 2 +- examples/ui/size_constraints.rs | 1 + 5 files changed, 27 insertions(+), 8 deletions(-) diff --git a/benches/benches/bevy_ecs/events/iter.rs b/benches/benches/bevy_ecs/events/iter.rs index 64684f5c734bf..4c5ed5375fa84 100644 --- a/benches/benches/bevy_ecs/events/iter.rs +++ b/benches/benches/bevy_ecs/events/iter.rs @@ -1,13 +1,16 @@ use bevy_ecs::prelude::*; -pub struct Benchmark(Events<[u8; SIZE]>); +#[derive(Event)] +struct BenchEvent([u8; SIZE]); + +pub struct Benchmark(Events>); impl Benchmark { pub fn new(count: usize) -> Self { let mut events = Events::default(); for _ in 0..count { - events.send([0u8; SIZE]); + events.send(BenchEvent([0u8; SIZE])); } Self(events) diff --git a/benches/benches/bevy_ecs/events/send.rs b/benches/benches/bevy_ecs/events/send.rs index ca816ab086685..2c81583d74ca1 100644 --- a/benches/benches/bevy_ecs/events/send.rs +++ b/benches/benches/bevy_ecs/events/send.rs @@ -1,18 +1,27 @@ use bevy_ecs::prelude::*; +#[derive(Event)] +struct BenchEvent([u8; SIZE]); + +impl Default for BenchEvent { + fn default() -> Self { + BenchEvent([0; SIZE]) + } +} + pub struct Benchmark { - events: Events<[u8; SIZE]>, + events: Events>, count: usize, } impl Benchmark { pub fn new(count: usize) -> Self { let mut events = Events::default(); - + // Force both internal buffers to be allocated. for _ in 0..2 { for _ in 0..count { - events.send([0u8; SIZE]); + events.send(BenchEvent([0u8; SIZE])); } events.update(); } @@ -22,7 +31,8 @@ impl Benchmark { pub fn run(&mut self) { for _ in 0..self.count { - self.events.send(std::hint::black_box([0u8; SIZE])); + self.events + .send(std::hint::black_box(BenchEvent([0u8; SIZE]))); } self.events.update(); } diff --git a/crates/bevy_ecs/src/schedule/condition.rs b/crates/bevy_ecs/src/schedule/condition.rs index 6b1d747e2773c..8ff15f116b98a 100644 --- a/crates/bevy_ecs/src/schedule/condition.rs +++ b/crates/bevy_ecs/src/schedule/condition.rs @@ -876,6 +876,7 @@ pub mod common_conditions { /// my_system.run_if(on_event::()), /// ); /// + /// #[derive(Event)] /// struct MyEvent; /// /// fn my_system(mut counter: ResMut) { @@ -1133,6 +1134,7 @@ mod tests { use crate::schedule::{common_conditions::not, State, States}; use crate::system::Local; use crate::{change_detection::ResMut, schedule::Schedule, world::World}; + use bevy_ecs_macros::Event; use bevy_ecs_macros::Resource; #[derive(Resource, Default)] @@ -1239,6 +1241,9 @@ mod tests { #[derive(Component)] struct TestComponent; + #[derive(Event)] + struct TestEvent; + fn test_system() {} // Ensure distributive_run_if compiles with the common conditions. @@ -1256,7 +1261,7 @@ mod tests { .distributive_run_if(state_exists::()) .distributive_run_if(in_state(TestState::A)) .distributive_run_if(state_changed::()) - .distributive_run_if(on_event::()) + .distributive_run_if(on_event::()) .distributive_run_if(any_with_component::()) .distributive_run_if(not(run_once())), ); diff --git a/crates/bevy_input/src/gamepad.rs b/crates/bevy_input/src/gamepad.rs index c43210ba1a0c3..00801d4e28acf 100644 --- a/crates/bevy_input/src/gamepad.rs +++ b/crates/bevy_input/src/gamepad.rs @@ -1330,7 +1330,7 @@ impl GamepadRumbleIntensity { #[doc(alias = "force feedback")] #[doc(alias = "vibration")] #[doc(alias = "vibrate")] -#[derive(Clone)] +#[derive(Event, Clone)] pub enum GamepadRumbleRequest { /// Add a rumble to the given gamepad. /// diff --git a/examples/ui/size_constraints.rs b/examples/ui/size_constraints.rs index 24ae9eb98ccfb..562a892bd93c1 100644 --- a/examples/ui/size_constraints.rs +++ b/examples/ui/size_constraints.rs @@ -35,6 +35,7 @@ enum Constraint { #[derive(Copy, Clone, Component)] struct ButtonValue(Val); +#[derive(Event)] struct ButtonActivatedEvent(Entity); fn setup(mut commands: Commands, asset_server: Res) { From ebbc1d60bd547a76b0620118895972dde6e748e1 Mon Sep 17 00:00:00 2001 From: CatThingy Date: Mon, 5 Jun 2023 18:25:38 -0700 Subject: [PATCH 16/16] Add missing `Event` derive --- crates/bevy_window/src/event.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_window/src/event.rs b/crates/bevy_window/src/event.rs index 7772f84ad49db..94f8be6b60712 100644 --- a/crates/bevy_window/src/event.rs +++ b/crates/bevy_window/src/event.rs @@ -297,7 +297,7 @@ pub struct WindowMoved { /// /// This event is only sent when the window is relying on the system theme to control its appearance. /// i.e. It is only sent when [`Window::window_theme`](crate::window::Window::window_theme) is `None` and the system theme changes. -#[derive(Debug, Clone, PartialEq, Eq, Reflect, FromReflect)] +#[derive(Event, Debug, Clone, PartialEq, Eq, Reflect, FromReflect)] #[reflect(Debug, PartialEq)] #[cfg_attr( feature = "serialize",