Path: blob/main/crates/bevy_ecs/src/reflect/message.rs
30636 views
//! Definitions for [`Message`] reflection.1//! This allows writing messages whose type is only known at runtime.2//!3//! This module exports two types: [`ReflectMessageFns`] and [`ReflectMessage`].4//!5//! Same as [`component`](`super::component`), but for messages.67use crate::{message::Message, reflect::from_reflect_with_fallback, world::World};8use bevy_reflect::{CreateTypeData, FromReflect, PartialReflect, Reflect, TypePath, TypeRegistry};910/// A struct used to operate on reflected [`Message`] trait of a type.11///12/// A [`ReflectMessage`] for type `T` can be obtained via13/// [`bevy_reflect::TypeRegistration::data`].14#[derive(Clone)]15pub struct ReflectMessage(ReflectMessageFns);1617/// The raw function pointers needed to make up a [`ReflectMessage`].18///19/// This is used when creating custom implementations of [`ReflectMessage`] with20/// [`ReflectMessage::new()`].21///22/// > **Note:**23/// > Creating custom implementations of [`ReflectMessage`] is an advanced feature24/// > that most users will not need. Usually a [`ReflectMessage`] is created for a25/// > type by deriving [`Reflect`] and adding the `#[reflect(Message)]` attribute.26/// > After adding the event to the [`TypeRegistry`], its [`ReflectMessage`] can27/// > then be retrieved when needed.28///29/// Creating a custom [`ReflectMessage`] may be useful if you need to create new30/// message types at runtime, for example, for scripting implementations.31///32/// By creating a custom [`ReflectMessage`] and inserting it into a type's33/// [`TypeRegistration`][bevy_reflect::TypeRegistration], you can modify the way34/// that reflected messages of that type will be written to the Bevy world.35#[derive(Clone)]36pub struct ReflectMessageFns {37/// Function pointer implementing [`ReflectMessage::write_message`].38pub write_message: fn(&mut World, &dyn PartialReflect, &TypeRegistry),39}4041impl ReflectMessageFns {42/// Get the default set of [`ReflectMessageFns`] for a specific event type43/// using its [`CreateTypeData`] implementation.44///45/// This is useful if you want to start with the default implementation46/// before overriding some of the functions to create a custom implementation.47pub fn new<M: Message + FromReflect + TypePath>() -> Self {48<ReflectMessage as CreateTypeData<M>>::create_type_data(()).049}50}5152impl ReflectMessage {53/// Triggers a reflected [`Message`] like [`write_message()`](World::write_message).54pub fn write_message(55&self,56world: &mut World,57message: &dyn PartialReflect,58registry: &TypeRegistry,59) {60(self.0.write_message)(world, message, registry);61}6263/// Create a custom implementation of [`ReflectMessage`].64///65/// This is an advanced feature,66/// useful for scripting implementations,67/// that should not be used by most users68/// unless you know what you are doing.69///70/// Usually you should derive [`Reflect`] and add the `#[reflect(Message)]`71/// attribute to generate a [`ReflectMessage`] implementation automatically.72///73/// See [`ReflectMessageFns`] for more information.74pub fn new(fns: ReflectMessageFns) -> Self {75ReflectMessage(fns)76}7778/// The underlying function pointers implementing methods on [`ReflectMessage`].79///80/// This is useful when you want to keep track locally of an individual81/// function pointer.82///83/// Calling [`TypeRegistry::get`] followed by84/// [`TypeRegistration::data::<ReflectMessage>`] can be costly if done several85/// times per frame. Consider cloning [`ReflectMessage`] and keeping it86/// between frames, cloning a `ReflectMessage` is very cheap.87///88/// If you only need a subset of the methods on `ReflectMessage`,89/// use `fn_pointers` to get the underlying [`ReflectMessageFns`]90/// and copy the subset of function pointers you care about.91///92/// [`TypeRegistration::data::<ReflectMessage>`]: bevy_reflect::TypeRegistration::data93/// [`TypeRegistry::get`]: bevy_reflect::TypeRegistry::get94pub fn fn_pointers(&self) -> &ReflectMessageFns {95&self.096}97}9899impl<M: Message + Reflect + TypePath> CreateTypeData<M> for ReflectMessage {100fn create_type_data(_input: ()) -> Self {101ReflectMessage(ReflectMessageFns {102write_message: |world, reflected_message, registry| {103let message = from_reflect_with_fallback::<M>(reflected_message, world, registry);104world.write_message(message);105},106})107}108}109110111