Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Require #[derive(Event)] on all Events #7086

Merged
merged 19 commits into from
Jun 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions benches/benches/bevy_ecs/events/iter.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
use bevy_ecs::prelude::*;

pub struct Benchmark<const SIZE: usize>(Events<[u8; SIZE]>);
#[derive(Event)]
struct BenchEvent<const SIZE: usize>([u8; SIZE]);

pub struct Benchmark<const SIZE: usize>(Events<BenchEvent<SIZE>>);

impl<const SIZE: usize> Benchmark<SIZE> {
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)
Expand Down
18 changes: 14 additions & 4 deletions benches/benches/bevy_ecs/events/send.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,27 @@
use bevy_ecs::prelude::*;

#[derive(Event)]
struct BenchEvent<const SIZE: usize>([u8; SIZE]);

impl<const SIZE: usize> Default for BenchEvent<SIZE> {
fn default() -> Self {
BenchEvent([0; SIZE])
}
}

pub struct Benchmark<const SIZE: usize> {
events: Events<[u8; SIZE]>,
events: Events<BenchEvent<SIZE>>,
count: usize,
}

impl<const SIZE: usize> Benchmark<SIZE> {
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();
}
Expand All @@ -22,7 +31,8 @@ impl<const SIZE: usize> Benchmark<SIZE> {

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();
}
Expand Down
6 changes: 5 additions & 1 deletion crates/bevy_a11y/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,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.
///
Expand Down
3 changes: 2 additions & 1 deletion crates/bevy_app/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,7 @@ impl App {
/// # use bevy_app::prelude::*;
/// # use bevy_ecs::prelude::*;
/// #
/// # #[derive(Event)]
/// # struct MyEvent;
/// # let mut app = App::new();
/// #
Expand Down Expand Up @@ -976,7 +977,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)]
Expand Down
1 change: 1 addition & 0 deletions crates/bevy_asset/src/assets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<T: Asset> {
#[allow(missing_docs)]
Created { handle: Handle<T> },
Expand Down
1 change: 1 addition & 0 deletions crates/bevy_ecs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
Expand Down
1 change: 1 addition & 0 deletions crates/bevy_ecs/examples/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,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,
Expand Down
18 changes: 18 additions & 0 deletions crates/bevy_ecs/macros/src/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,24 @@ use proc_macro2::{Span, TokenStream as TokenStream2};
use quote::quote;
use syn::{parse_macro_input, parse_quote, DeriveInput, Ident, LitStr, 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();
Expand Down
5 changes: 5 additions & 0 deletions crates/bevy_ecs/macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,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)
Expand Down
16 changes: 10 additions & 6 deletions crates/bevy_ecs/src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

use crate as bevy_ecs;
use crate::system::{Local, Res, ResMut, Resource, SystemParam};
pub use bevy_ecs_macros::Event;
use bevy_utils::detailed_trace;
use std::ops::{Deref, DerefMut};
use std::{
Expand All @@ -17,7 +18,6 @@ use std::{
///
/// Events must be thread-safe.
pub trait Event: Send + Sync + 'static {}
impl<T> Event for T where T: Send + Sync + 'static {}

/// An `EventId` uniquely identifies an event.
///
Expand Down Expand Up @@ -109,8 +109,9 @@ struct EventInstance<E: Event> {
///
/// # Example
/// ```
/// use bevy_ecs::event::Events;
/// use bevy_ecs::event::{Event, Events};
///
/// #[derive(Event)]
/// struct MyEvent {
/// value: usize
/// }
Expand Down Expand Up @@ -248,6 +249,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<CollisionEvent>) {
Expand Down Expand Up @@ -289,6 +292,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<MyEvent>) {
/// writer.send(MyEvent);
Expand All @@ -305,7 +309,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
Expand Down Expand Up @@ -699,7 +703,7 @@ mod tests {

use super::*;

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[derive(Event, Copy, Clone, PartialEq, Eq, Debug)]
struct TestEvent {
i: usize,
}
Expand Down Expand Up @@ -802,7 +806,7 @@ mod tests {
reader.iter(events).cloned().collect::<Vec<E>>()
}

#[derive(PartialEq, Eq, Debug)]
#[derive(Event, PartialEq, Eq, Debug)]
struct E(usize);

fn events_clear_and_read_impl(clear_func: impl FnOnce(&mut Events<E>)) {
Expand Down Expand Up @@ -1009,7 +1013,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]
Expand Down
6 changes: 4 additions & 2 deletions crates/bevy_ecs/src/removal_detection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ use crate::{
self as bevy_ecs,
component::{Component, ComponentId, ComponentIdFor, Tick},
entity::Entity,
event::{EventId, Events, ManualEventIterator, ManualEventIteratorWithId, ManualEventReader},
event::{
Event, EventId, Events, ManualEventIterator, ManualEventIteratorWithId, ManualEventReader,
},
prelude::Local,
storage::SparseSet,
system::{ReadOnlySystemParam, SystemMeta, SystemParam},
Expand All @@ -21,7 +23,7 @@ use std::{

/// Wrapper around [`Entity`] for [`RemovedComponents`].
/// Internally, `RemovedComponents` uses these as an `Events<RemovedComponentEntity>`.
#[derive(Debug, Clone)]
#[derive(Event, Debug, Clone)]
pub struct RemovedComponentEntity(Entity);

impl From<RemovedComponentEntity> for Entity {
Expand Down
7 changes: 6 additions & 1 deletion crates/bevy_ecs/src/schedule/condition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -876,6 +876,7 @@ pub mod common_conditions {
/// my_system.run_if(on_event::<MyEvent>()),
/// );
///
/// #[derive(Event)]
/// struct MyEvent;
///
/// fn my_system(mut counter: ResMut<Counter>) {
Expand Down Expand Up @@ -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)]
Expand Down Expand Up @@ -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.
Expand All @@ -1256,7 +1261,7 @@ mod tests {
.distributive_run_if(state_exists::<TestState>())
.distributive_run_if(in_state(TestState::A))
.distributive_run_if(state_changed::<TestState>())
.distributive_run_if(on_event::<u8>())
.distributive_run_if(on_event::<TestEvent>())
.distributive_run_if(any_with_component::<TestComponent>())
.distributive_run_if(not(run_once())),
);
Expand Down
2 changes: 2 additions & 0 deletions crates/bevy_ecs/src/system/function_system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ impl SystemMeta {
/// # use bevy_ecs::system::SystemState;
/// # use bevy_ecs::event::Events;
/// #
/// # #[derive(Event)]
/// # struct MyEvent;
/// # #[derive(Resource)]
/// # struct MyResource(u32);
Expand Down Expand Up @@ -117,6 +118,7 @@ impl SystemMeta {
/// # use bevy_ecs::system::SystemState;
/// # use bevy_ecs::event::Events;
/// #
/// # #[derive(Event)]
/// # struct MyEvent;
/// #[derive(Resource)]
/// struct CachedSystemState {
Expand Down
1 change: 1 addition & 0 deletions crates/bevy_ecs/src/system/system_param.rs
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,7 @@ fn assert_component_access_compatibility(
/// ```
/// # use bevy_ecs::prelude::*;
/// #
/// # #[derive(Event)]
/// # struct MyEvent;
/// # impl MyEvent {
/// # pub fn new() -> Self { Self }
Expand Down
4 changes: 2 additions & 2 deletions crates/bevy_hierarchy/src/events.rs
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down
12 changes: 6 additions & 6 deletions crates/bevy_input/src/gamepad.rs
Original file line number Diff line number Diff line change
@@ -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},
Expand Down Expand Up @@ -1039,7 +1039,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",
Expand Down Expand Up @@ -1070,7 +1070,7 @@ impl GamepadConnectionEvent {
}
}

#[derive(Debug, Clone, PartialEq, Reflect, FromReflect)]
#[derive(Event, Debug, Clone, PartialEq, Reflect, FromReflect)]
#[reflect(Debug, PartialEq)]
#[cfg_attr(
feature = "serialize",
Expand All @@ -1095,7 +1095,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",
Expand Down Expand Up @@ -1158,7 +1158,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",
Expand Down Expand Up @@ -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.
///
Expand Down
8 changes: 6 additions & 2 deletions crates/bevy_input/src/keyboard.rs
Original file line number Diff line number Diff line change
@@ -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")]
Expand All @@ -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<KeyCode>`](crate::Input<KeyCode>) 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",
Expand Down
Loading