Revert changes related mutual exclusivity + minor docs and release note changes
This commit is contained in:
parent
779e4535d9
commit
1161216938
@ -30,9 +30,8 @@ pub fn derive_broadcast_event(input: TokenStream) -> TokenStream {
|
|||||||
let (impl_generics, type_generics, where_clause) = &ast.generics.split_for_impl();
|
let (impl_generics, type_generics, where_clause) = &ast.generics.split_for_impl();
|
||||||
|
|
||||||
TokenStream::from(quote! {
|
TokenStream::from(quote! {
|
||||||
impl #impl_generics #bevy_ecs_path::event::Event for #struct_name #type_generics #where_clause {
|
impl #impl_generics #bevy_ecs_path::event::Event for #struct_name #type_generics #where_clause {}
|
||||||
type Kind = #bevy_ecs_path::event::BroadcastEventKind;
|
impl #impl_generics #bevy_ecs_path::event::BroadcastEvent for #struct_name #type_generics #where_clause {}
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,8 +74,10 @@ pub fn derive_entity_event(input: TokenStream) -> TokenStream {
|
|||||||
let (impl_generics, type_generics, where_clause) = &ast.generics.split_for_impl();
|
let (impl_generics, type_generics, where_clause) = &ast.generics.split_for_impl();
|
||||||
|
|
||||||
TokenStream::from(quote! {
|
TokenStream::from(quote! {
|
||||||
impl #impl_generics #bevy_ecs_path::event::Event for #struct_name #type_generics #where_clause {
|
impl #impl_generics #bevy_ecs_path::event::Event for #struct_name #type_generics #where_clause {}
|
||||||
type Kind = #bevy_ecs_path::event::EntityEventKind<Self, #traversal, #auto_propagate>;
|
impl #impl_generics #bevy_ecs_path::event::EntityEvent for #struct_name #type_generics #where_clause {
|
||||||
|
type Traversal = #traversal;
|
||||||
|
const AUTO_PROPAGATE: bool = #auto_propagate;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -95,9 +95,6 @@ use core::{
|
|||||||
note = "consider annotating `{Self}` with `#[derive(BroadcastEvent)]` or `#[derive(EntityEvent)]`"
|
note = "consider annotating `{Self}` with `#[derive(BroadcastEvent)]` or `#[derive(EntityEvent)]`"
|
||||||
)]
|
)]
|
||||||
pub trait Event: Send + Sync + 'static {
|
pub trait Event: Send + Sync + 'static {
|
||||||
#[doc(hidden)]
|
|
||||||
type Kind;
|
|
||||||
|
|
||||||
/// Generates the [`EventKey`] for this event type.
|
/// Generates the [`EventKey`] for this event type.
|
||||||
///
|
///
|
||||||
/// If this type has already been registered,
|
/// If this type has already been registered,
|
||||||
@ -133,32 +130,7 @@ pub trait Event: Send + Sync + 'static {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A global [`Event`] without an entity target.
|
/// A global [`Event`] without an entity target.
|
||||||
#[diagnostic::on_unimplemented(
|
pub trait BroadcastEvent: Event {}
|
||||||
message = "`{Self}` is not an `BroadcastEvent`",
|
|
||||||
label = "invalid `BroadcastEvent`",
|
|
||||||
note = "consider annotating `{Self}` with `#[derive(BroadcastEvent)]`"
|
|
||||||
)]
|
|
||||||
pub trait BroadcastEvent: Event + sealed_a::SealedA {}
|
|
||||||
|
|
||||||
#[doc(hidden)]
|
|
||||||
pub struct BroadcastEventKind;
|
|
||||||
|
|
||||||
#[diagnostic::do_not_recommend]
|
|
||||||
impl<T> BroadcastEvent for T where T: Event<Kind = BroadcastEventKind> {}
|
|
||||||
|
|
||||||
pub(crate) mod sealed_a {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
/// Seal for the [`BroadcastEvent`] trait.
|
|
||||||
#[diagnostic::on_unimplemented(
|
|
||||||
message = "manual implementations of `BroadcastEvent` are disallowed",
|
|
||||||
note = "consider annotating `{Self}` with `#[derive(BroadcastEvent)]` instead"
|
|
||||||
)]
|
|
||||||
pub trait SealedA {}
|
|
||||||
|
|
||||||
#[diagnostic::do_not_recommend]
|
|
||||||
impl<T> SealedA for T where T: Event<Kind = BroadcastEventKind> {}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// An [`Event`] that can be targeted at specific entities.
|
/// An [`Event`] that can be targeted at specific entities.
|
||||||
///
|
///
|
||||||
@ -276,7 +248,7 @@ pub(crate) mod sealed_a {
|
|||||||
label = "invalid `EntityEvent`",
|
label = "invalid `EntityEvent`",
|
||||||
note = "consider annotating `{Self}` with `#[derive(EntityEvent)]`"
|
note = "consider annotating `{Self}` with `#[derive(EntityEvent)]`"
|
||||||
)]
|
)]
|
||||||
pub trait EntityEvent: Event + sealed_b::SealedB {
|
pub trait EntityEvent: Event {
|
||||||
/// The component that describes which [`Entity`] to propagate this event to next, when [propagation] is enabled.
|
/// The component that describes which [`Entity`] to propagate this event to next, when [propagation] is enabled.
|
||||||
///
|
///
|
||||||
/// [`Entity`]: crate::entity::Entity
|
/// [`Entity`]: crate::entity::Entity
|
||||||
@ -291,37 +263,6 @@ pub trait EntityEvent: Event + sealed_b::SealedB {
|
|||||||
const AUTO_PROPAGATE: bool = false;
|
const AUTO_PROPAGATE: bool = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
|
||||||
pub struct EntityEventKind<T: ?Sized, R: Traversal<T>, const A: bool> {
|
|
||||||
_t: PhantomData<T>,
|
|
||||||
_r: PhantomData<R>,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Blanket impl for EntityEvent
|
|
||||||
#[diagnostic::do_not_recommend]
|
|
||||||
impl<T, R: Traversal<T>, const A: bool> EntityEvent for T
|
|
||||||
where
|
|
||||||
T: Event<Kind = EntityEventKind<T, R, A>>,
|
|
||||||
{
|
|
||||||
type Traversal = R;
|
|
||||||
const AUTO_PROPAGATE: bool = A;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) mod sealed_b {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
/// Seal for the [`EntityEvent`] trait.
|
|
||||||
#[diagnostic::on_unimplemented(
|
|
||||||
message = "manual implementations of `EntityEvent` are disallowed",
|
|
||||||
note = "consider annotating `{Self}` with `#[derive(EntityEvent)]` instead"
|
|
||||||
)]
|
|
||||||
pub trait SealedB {}
|
|
||||||
|
|
||||||
#[diagnostic::do_not_recommend]
|
|
||||||
impl<T, R: Traversal<T>, const A: bool> SealedB for T where T: Event<Kind = EntityEventKind<T, R, A>>
|
|
||||||
{}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A buffered event for pull-based event handling.
|
/// A buffered event for pull-based event handling.
|
||||||
///
|
///
|
||||||
/// Buffered events can be written with [`EventWriter`] and read using the [`EventReader`] system parameter.
|
/// Buffered events can be written with [`EventWriter`] and read using the [`EventReader`] system parameter.
|
||||||
|
|||||||
@ -11,10 +11,7 @@ mod update;
|
|||||||
mod writer;
|
mod writer;
|
||||||
|
|
||||||
pub(crate) use base::EventInstance;
|
pub(crate) use base::EventInstance;
|
||||||
pub use base::{
|
pub use base::{BroadcastEvent, BufferedEvent, EntityEvent, Event, EventId, EventKey};
|
||||||
BroadcastEvent, BroadcastEventKind, BufferedEvent, EntityEvent, EntityEventKind, Event,
|
|
||||||
EventId, EventKey,
|
|
||||||
};
|
|
||||||
pub use bevy_ecs_macros::{BroadcastEvent, BufferedEvent, EntityEvent};
|
pub use bevy_ecs_macros::{BroadcastEvent, BufferedEvent, EntityEvent};
|
||||||
#[expect(deprecated, reason = "`SendBatchIds` was renamed to `WriteBatchIds`.")]
|
#[expect(deprecated, reason = "`SendBatchIds` was renamed to `WriteBatchIds`.")]
|
||||||
pub use collections::{Events, SendBatchIds, WriteBatchIds};
|
pub use collections::{Events, SendBatchIds, WriteBatchIds};
|
||||||
|
|||||||
@ -110,15 +110,19 @@ impl<'w, E: EntityEvent, B: Bundle> On<'w, E, B> {
|
|||||||
///
|
///
|
||||||
/// Note that if event propagation is enabled, this may not be the same as the original target of the event,
|
/// Note that if event propagation is enabled, this may not be the same as the original target of the event,
|
||||||
/// which can be accessed via [`On::original_target`].
|
/// which can be accessed via [`On::original_target`].
|
||||||
|
///
|
||||||
|
/// If the event is also a [`BroadcastEvent`] sent with [`trigger`](World::trigger), this will return [`Entity::PLACEHOLDER`].
|
||||||
pub fn target(&self) -> Entity {
|
pub fn target(&self) -> Entity {
|
||||||
self.trigger.current_target.unwrap()
|
self.trigger.current_target.unwrap_or(Entity::PLACEHOLDER)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the original [`Entity`] that the [`EntityEvent`] was targeted at when it was first triggered.
|
/// Returns the original [`Entity`] that the [`EntityEvent`] was targeted at when it was first triggered.
|
||||||
///
|
///
|
||||||
/// If event propagation is not enabled, this will always return the same value as [`On::target`].
|
/// If event propagation is not enabled, this will always return the same value as [`On::target`].
|
||||||
|
///
|
||||||
|
/// If the event is also a [`BroadcastEvent`] sent with [`trigger`](World::trigger), this will return [`Entity::PLACEHOLDER`].
|
||||||
pub fn original_target(&self) -> Entity {
|
pub fn original_target(&self) -> Entity {
|
||||||
self.trigger.original_target.unwrap()
|
self.trigger.original_target.unwrap_or(Entity::PLACEHOLDER)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enables or disables event propagation, allowing the same event to trigger observers on a chain of different entities.
|
/// Enables or disables event propagation, allowing the same event to trigger observers on a chain of different entities.
|
||||||
@ -181,11 +185,13 @@ pub struct ObserverTrigger {
|
|||||||
pub event_key: EventKey,
|
pub event_key: EventKey,
|
||||||
/// The [`ComponentId`]s the trigger targeted.
|
/// The [`ComponentId`]s the trigger targeted.
|
||||||
pub components: SmallVec<[ComponentId; 2]>,
|
pub components: SmallVec<[ComponentId; 2]>,
|
||||||
/// For [`EntityEvent`]s this is the entity that the event targeted. Always `None` for [`BroadcastEvent`].
|
/// For [`EntityEvent`]s used with `trigger_targets` this is the entity that the event targeted.
|
||||||
|
/// Can only be `None` for [`BroadcastEvent`]s used with `trigger`.
|
||||||
///
|
///
|
||||||
/// Note that if event propagation is enabled, this may not be the same as [`ObserverTrigger::original_target`].
|
/// Note that if event propagation is enabled, this may not be the same as [`ObserverTrigger::original_target`].
|
||||||
pub current_target: Option<Entity>,
|
pub current_target: Option<Entity>,
|
||||||
/// For [`EntityEvent`]s this is the entity that the event was originally targeted at. Always `None` for [`BroadcastEvent`].
|
/// For [`EntityEvent`]s used with `trigger_targets` this is the entity that the event was originally targeted at.
|
||||||
|
/// Can only be `None` for [`BroadcastEvent`]s used with `trigger`.
|
||||||
///
|
///
|
||||||
/// If event propagation is enabled, this will be the first entity that the event was targeted at,
|
/// If event propagation is enabled, this will be the first entity that the event was targeted at,
|
||||||
/// even if the event was propagated to other entities.
|
/// even if the event was propagated to other entities.
|
||||||
|
|||||||
@ -2,7 +2,7 @@ use crate::{DynamicScene, Scene};
|
|||||||
use bevy_asset::{AssetEvent, AssetId, Assets, Handle};
|
use bevy_asset::{AssetEvent, AssetId, Assets, Handle};
|
||||||
use bevy_ecs::{
|
use bevy_ecs::{
|
||||||
entity::{Entity, EntityHashMap},
|
entity::{Entity, EntityHashMap},
|
||||||
event::{EntityEvent, EventCursor, Events},
|
event::{BroadcastEvent, EntityEvent, EventCursor, Events},
|
||||||
hierarchy::ChildOf,
|
hierarchy::ChildOf,
|
||||||
reflect::AppTypeRegistry,
|
reflect::AppTypeRegistry,
|
||||||
resource::Resource,
|
resource::Resource,
|
||||||
@ -34,6 +34,8 @@ pub struct SceneInstanceReady {
|
|||||||
pub instance_id: InstanceId,
|
pub instance_id: InstanceId,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl BroadcastEvent for SceneInstanceReady {}
|
||||||
|
|
||||||
/// Information about a scene instance.
|
/// Information about a scene instance.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct InstanceInfo {
|
pub struct InstanceInfo {
|
||||||
@ -421,8 +423,7 @@ impl SceneSpawner {
|
|||||||
.trigger_targets(SceneInstanceReady { instance_id }, parent);
|
.trigger_targets(SceneInstanceReady { instance_id }, parent);
|
||||||
} else {
|
} else {
|
||||||
// Defer via commands otherwise SceneSpawner is not available in the observer.
|
// Defer via commands otherwise SceneSpawner is not available in the observer.
|
||||||
// TODO: Thinkies
|
world.commands().trigger(SceneInstanceReady { instance_id });
|
||||||
// world.commands().trigger(SceneInstanceReady { instance_id });
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,7 +25,7 @@ APIs are typically built to support only one of them.
|
|||||||
|
|
||||||
This has led to a lot of confusion and frustration for users. Common footguns include:
|
This has led to a lot of confusion and frustration for users. Common footguns include:
|
||||||
- Using a "buffered event" with an observer, or an observer event with `EventReader`, leaving the user wondering why the event is not being detected.
|
- Using a "buffered event" with an observer, or an observer event with `EventReader`, leaving the user wondering why the event is not being detected.
|
||||||
- `On`(formerly `Trigger`) has a `target` getter which would return `Entity::PLACEHOLDER` for events sent via `trigger` rather than `trigger_targets`.
|
- `On`(formerly `Trigger`) has a `target` getter which would cause confusion for events only mean to be used with `trigger` where it returns `Entity::PLACEHOLDER`.
|
||||||
|
|
||||||
**Bevy 0.17** aims to solve this ambiguity by splitting the different kinds of events into multiple traits:
|
**Bevy 0.17** aims to solve this ambiguity by splitting the different kinds of events into multiple traits:
|
||||||
|
|
||||||
@ -34,8 +34,6 @@ This has led to a lot of confusion and frustration for users. Common footguns in
|
|||||||
- `EntityEvent`: An observer event that targets specific entities and can propagate the event from one entity to another across relationships.
|
- `EntityEvent`: An observer event that targets specific entities and can propagate the event from one entity to another across relationships.
|
||||||
- `BufferedEvent`: An event used with `EventReader` and `EventWriter` for pull-based event handling.
|
- `BufferedEvent`: An event used with `EventReader` and `EventWriter` for pull-based event handling.
|
||||||
|
|
||||||
Note: To fully prevent the footgun of `On::target` returning `Entity::PLACEHOLDER` the `BroadcastEvent` and `EntityEvent` traits were made mutually exclusive.
|
|
||||||
|
|
||||||
## Using Events
|
## Using Events
|
||||||
|
|
||||||
Events without an entity target can be defined, by deriving the `BroadcastEvent` trait.
|
Events without an entity target can be defined, by deriving the `BroadcastEvent` trait.
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user