From bb9706c96f5edc536bd7148f869615350ac13c8a Mon Sep 17 00:00:00 2001 From: JoJoJet Date: Wed, 13 Jul 2022 14:40:52 +0000 Subject: [PATCH] Document exotic patterns for `Command`s and `Event`s (#4840) # Objective Improve documentation, information users of the limitations in bevy's idiomatic patterns, and suggesting alternatives for when those limitations are encountered. ## Solution * Add documentation to `Commands` informing the user of the option of writing one-shot commands with closures. * Add documentation to `EventWriter` regarding the limitations of event types, and suggesting alternatives using commands. --- crates/bevy_ecs/src/event.rs | 42 ++++++++++++++++++++++ crates/bevy_ecs/src/system/commands/mod.rs | 22 ++++++++++-- 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/crates/bevy_ecs/src/event.rs b/crates/bevy_ecs/src/event.rs index ac473ab3f1..598d1287d4 100644 --- a/crates/bevy_ecs/src/event.rs +++ b/crates/bevy_ecs/src/event.rs @@ -249,6 +249,48 @@ impl<'w, 's, E: Event> EventReader<'w, 's, E> { } /// Sends events of type `T`. +/// +/// # Usage +/// +/// `EventWriter`s are usually declared as a [`SystemParam`]. +/// ``` +/// # use bevy_ecs::prelude::*; +/// +/// pub struct MyEvent; // Custom event type. +/// fn my_system(mut writer: EventWriter) { +/// writer.send(MyEvent); +/// } +/// +/// # bevy_ecs::system::assert_is_system(my_system); +/// ``` +/// +/// # Limitations +/// +/// `EventWriter` can only send events of one specific type, which must be known at compile-time. +/// This is not a problem most of the time, but you may find a situtation where you cannot know +/// ahead of time every kind of event you'll need to send. In this case, you can use the "type-erased event" pattern. +/// +/// ``` +/// # use bevy_ecs::{prelude::*, event::Events}; +/// +/// # pub struct MyEvent; +/// fn send_untyped(mut commands: Commands) { +/// // Send an event of a specific type without having to declare that +/// // type as a SystemParam. +/// // +/// // Effectively, we're just moving the type parameter from the /type/ to the /method/, +/// // which allows one to do all kinds of clever things with type erasure, such as sending +/// // custom events to unknown 3rd party plugins (modding API). +/// // +/// // NOTE: the event won't actually be sent until commands get flushed +/// // at the end of the current stage. +/// commands.add(|w: &mut World| { +/// let mut events_resource = w.resource_mut::>(); +/// events_resource.send(MyEvent); +/// }); +/// } +/// ``` +/// Note that this is considered *non-idiomatic*, and should only be used when `EventWriter` will not work. #[derive(SystemParam)] pub struct EventWriter<'w, 's, E: Event> { events: ResMut<'w, Events>, diff --git a/crates/bevy_ecs/src/system/commands/mod.rs b/crates/bevy_ecs/src/system/commands/mod.rs index 9888edac18..1521eebe52 100644 --- a/crates/bevy_ecs/src/system/commands/mod.rs +++ b/crates/bevy_ecs/src/system/commands/mod.rs @@ -66,10 +66,28 @@ pub trait Command: Send + Sync + 'static { /// fn my_system(mut commands: Commands) { /// // ... /// } +/// # bevy_ecs::system::assert_is_system(my_system); /// ``` /// -/// Each command is implemented as a separate method. -/// Check the [`Command`] trait for a list of available commands (or implement your own!). +/// # Implementing +/// +/// Each built-in command is implemented as a separate method, e.g. [`spawn`](#method.spawn). +/// In addition to the pre-defined command methods, you can add commands with any arbitrary +/// behavior using [`Commands::add`](#method.add), which accepts any type implementing [`Command`]. +/// +/// Since closures and other functions implement this trait automatically, this allows one-shot, +/// anonymous custom commands. +/// +/// ``` +/// # use bevy_ecs::prelude::*; +/// # fn foo(mut commands: Commands) { +/// // NOTE: type inference fails here, so annotations are required on the closure. +/// commands.add(|w: &mut World| { +/// // Mutate the world however you want... +/// # todo!(); +/// }); +/// # } +/// ``` pub struct Commands<'w, 's> { queue: &'s mut CommandQueue, entities: &'w Entities,