Skip to content
Open
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
68 changes: 51 additions & 17 deletions crates/bevy_ecs/src/reflect/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,34 +18,33 @@ pub struct ReflectEvent(ReflectEventFns);
/// The raw function pointers needed to make up a [`ReflectEvent`].
///
/// This is used when creating custom implementations of [`ReflectEvent`] with
/// [`ReflectEventFns::new()`].
/// [`ReflectEvent::new()`].
///
/// > **Note:**
/// > Creating custom implementations of [`ReflectEvent`] is an advanced feature that most users
/// > will not need.
/// > Usually a [`ReflectEvent`] is created for a type by deriving [`Reflect`]
/// > and adding the `#[reflect(Event)]` attribute.
/// > After adding the component to the [`TypeRegistry`],
/// > its [`ReflectEvent`] can then be retrieved when needed.
/// > Creating custom implementations of [`ReflectEvent`] is an advanced feature
/// > that most users will not need. Usually a [`ReflectEvent`] is created for a
/// > type by deriving [`Reflect`] and adding the `#[reflect(Event)]` attribute.
/// > After adding the event to the [`TypeRegistry`], its [`ReflectEvent`] can
/// > then be retrieved when needed.
///
/// Creating a custom [`ReflectEvent`] may be useful if you need to create new component types
/// at runtime, for example, for scripting implementations.
/// Creating a custom [`ReflectEvent`] may be useful if you need to create new
/// event types at runtime, for example, for scripting implementations.
///
/// By creating a custom [`ReflectEvent`] and inserting it into a type's
/// [`TypeRegistration`][bevy_reflect::TypeRegistration],
/// you can modify the way that reflected event of that type will be triggered in the Bevy
/// world.
/// [`TypeRegistration`][bevy_reflect::TypeRegistration], you can modify the way
/// that reflected event of that type will be triggered in the Bevy world.
#[derive(Clone)]
pub struct ReflectEventFns {
trigger: fn(&mut World, &dyn PartialReflect, &TypeRegistry),
/// Function pointer implementing [`ReflectEvent::trigger`].
pub trigger: fn(&mut World, &dyn PartialReflect, &TypeRegistry),
}

impl ReflectEventFns {
/// Get the default set of [`ReflectEventFns`] for a specific event type using its
/// [`FromType`] implementation.
/// Get the default set of [`ReflectEventFns`] for a specific event type
/// using its [`FromType`] implementation.
///
/// This is useful if you want to start with the default implementation before overriding some
/// of the functions to create a custom implementation.
/// This is useful if you want to start with the default implementation
/// before overriding some of the functions to create a custom implementation.
pub fn new<'a, T: Event + FromReflect + TypePath>() -> Self
where
T::Trigger<'a>: Default,
Expand All @@ -59,6 +58,41 @@ impl ReflectEvent {
pub fn trigger(&self, world: &mut World, event: &dyn PartialReflect, registry: &TypeRegistry) {
(self.0.trigger)(world, event, registry);
}

/// Create a custom implementation of [`ReflectEvent`].
///
/// This is an advanced feature,
/// useful for scripting implementations,
/// that should not be used by most users
/// unless you know what you are doing.
///
/// Usually you should derive [`Reflect`] and add the `#[reflect(Event)]`
/// attribute to generate a [`ReflectEvent`] implementation automatically.
///
/// See [`ReflectEventFns`] for more information.
pub fn new(fns: ReflectEventFns) -> Self {
ReflectEvent(fns)
}

/// The underlying function pointers implementing methods on [`ReflectEvent`].
///
/// This is useful when you want to keep track locally of an individual
/// function pointer.
///
/// Calling [`TypeRegistry::get`] followed by
/// [`TypeRegistration::data::<ReflectEvent>`] can be costly if done several
/// times per frame. Consider cloning [`ReflectEvent`] and keeping it
/// between frames, cloning a `ReflectEvent` is very cheap.
///
/// If you only need a subset of the methods on `ReflectEvent`,
/// use `fn_pointers` to get the underlying [`ReflectEventFns`]
/// and copy the subset of function pointers you care about.
///
/// [`TypeRegistration::data::<ReflectEvent>`]: bevy_reflect::TypeRegistration::data
/// [`TypeRegistry::get`]: bevy_reflect::TypeRegistry::get
pub fn fn_pointers(&self) -> &ReflectEventFns {
&self.0
}
}

impl<'a, E: Event + Reflect + TypePath> FromType<E> for ReflectEvent
Expand Down