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

# Objective

Be consistent with `Resource`s and `Components` and have `Event` types
be more self-documenting.
Although not susceptible to accidentally using a function instead of a
value due to `Event`s only being initialized by their type, much of the
same reasoning for removing the blanket impl on `Resource` also applies
here.

* Not immediately obvious if a type is intended to be an event
* Prevent invisible conflicts if the same third-party or primitive types
are used as events
* Allows for further extensions (e.g. opt-in warning for missed events)

## Solution

Remove the blanket impl for the `Event` trait. Add a derive macro for
it.

---

## Changelog

- `Event` is no longer implemented for all applicable types. Add the
`#[derive(Event)]` macro for events.

## Migration Guide

* Add the `#[derive(Event)]` macro for events. Third-party types used as
events should be wrapped in a newtype.
This commit is contained in:
CatThingy 2023-06-06 07:44:32 -07:00 committed by GitHub
parent 1e97c79ec1
commit 89cbc78d3d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 130 additions and 54 deletions

View file

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

View file

@ -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();
}
@ -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();
}

View file

@ -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.
///

View file

@ -522,6 +522,7 @@ impl App {
/// # use bevy_app::prelude::*;
/// # use bevy_ecs::prelude::*;
/// #
/// # #[derive(Event)]
/// # struct MyEvent;
/// # let mut app = App::new();
/// #
@ -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)]

View file

@ -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> },

View file

@ -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,
}

View file

@ -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,

View file

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

View file

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

View file

@ -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::{
@ -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.
///
@ -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
/// }
@ -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>) {
@ -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);
@ -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
@ -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,
}
@ -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>)) {
@ -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]

View file

@ -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},
@ -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 {

View file

@ -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>) {
@ -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::<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())),
);

View file

@ -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);
@ -117,6 +118,7 @@ impl SystemMeta {
/// # use bevy_ecs::system::SystemState;
/// # use bevy_ecs::event::Events;
/// #
/// # #[derive(Event)]
/// # struct MyEvent;
/// #[derive(Resource)]
/// struct CachedSystemState {

View file

@ -308,6 +308,7 @@ fn assert_component_access_compatibility(
/// ```
/// # use bevy_ecs::prelude::*;
/// #
/// # #[derive(Event)]
/// # struct MyEvent;
/// # impl MyEvent {
/// # pub fn new() -> Self { Self }

View file

@ -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 {

View file

@ -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},
@ -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",
@ -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",
@ -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",
@ -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",
@ -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.
///

View file

@ -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<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",

View file

@ -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<MouseButton>`](crate::Input<MouseButton>) 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",

View file

@ -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",

View file

@ -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};
@ -10,7 +11,7 @@ use bevy_reflect::{ReflectDeserialize, ReflectSerialize};
use crate::WindowTheme;
/// 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",
@ -28,7 +29,7 @@ pub struct WindowResized {
/// An event that indicates all of the application's windows should be redrawn,
/// even if their 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",
@ -40,7 +41,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",
@ -62,7 +63,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",
@ -76,7 +77,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`](crate::window::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",
@ -99,7 +100,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",
@ -114,7 +115,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",
@ -127,7 +128,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",
@ -140,7 +141,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",
@ -159,7 +160,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",
@ -201,7 +202,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",
@ -216,7 +217,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",
@ -231,7 +232,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",
@ -246,7 +247,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",
@ -278,7 +279,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",
@ -296,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",

View file

@ -6,6 +6,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,
@ -73,11 +74,14 @@ fn window_closed(
}
}
fn poll_receivers(handlers: Res<WinitActionHandlers>, mut actions: EventWriter<ActionRequest>) {
fn poll_receivers(
handlers: Res<WinitActionHandlers>,
mut actions: EventWriter<ActionRequestWrapper>,
) {
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));
}
}
}
@ -164,7 +168,7 @@ impl Plugin for AccessibilityPlugin {
fn build(&self, app: &mut App) {
app.init_non_send_resource::<AccessKitAdapters>()
.init_resource::<WinitActionHandlers>()
.add_event::<ActionRequest>()
.add_event::<ActionRequestWrapper>()
.add_systems(
PostUpdate,
(

View file

@ -17,6 +17,8 @@ fn main() {
#[derive(Resource, Deref)]
struct StreamReceiver(Receiver<u32>);
#[derive(Event)]
struct StreamEvent(u32);
fn setup(mut commands: Commands) {

View file

@ -13,11 +13,12 @@ fn main() {
.run();
}
#[derive(Event)]
struct MyEvent {
pub message: String,
}
#[derive(Default)]
#[derive(Event, Default)]
struct PlaySound;
#[derive(Resource)]

View file

@ -84,7 +84,7 @@ struct Velocity(Vec2);
#[derive(Component)]
struct Collider;
#[derive(Default)]
#[derive(Event, Default)]
struct CollisionEvent;
#[derive(Component)]

View file

@ -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<AssetServer>) {

View file

@ -6,6 +6,7 @@ struct Enemy {
score_value: u32,
}
#[derive(Event)]
struct EnemyDied(u32);
#[derive(Resource)]