diff --git a/crates/bevy_app/src/plugin_group.rs b/crates/bevy_app/src/plugin_group.rs index 002b00799d443..a67b7645a43e3 100644 --- a/crates/bevy_app/src/plugin_group.rs +++ b/crates/bevy_app/src/plugin_group.rs @@ -37,11 +37,15 @@ use log::{debug, warn}; /// # pub struct TickratePlugin; /// # impl Plugin for TickratePlugin { fn build(&self, _: &mut App) {} } /// # +/// # pub fn bullet_time_plugin(_: &mut App) {} +/// # /// # mod features { /// # use bevy_app::*; /// # #[derive(Default)] /// # pub struct ForcePlugin; /// # impl Plugin for ForcePlugin { fn build(&self, _: &mut App) {} } +/// # +/// # pub fn force_debug_plugin(_: &mut App) {} /// # } /// # /// # mod web { @@ -67,6 +71,8 @@ use log::{debug, warn}; /// # #[derive(Default)] /// # pub struct InternalPlugin; /// # impl Plugin for InternalPlugin { fn build(&self, _: &mut App) {} } +/// # +/// # pub fn internal_plugin(_: &mut App) {} /// # } /// # /// plugin_group! { @@ -94,9 +100,17 @@ use log::{debug, warn}; /// #[plugin_group] /// audio:::AudioPlugins, /// // You can hide plugins from documentation. Due to macro limitations, hidden plugins -/// // must be last. +/// // must be after all other plugins. /// #[doc(hidden)] -/// internal:::InternalPlugin +/// internal:::InternalPlugin, +/// // Can end with a "fn block" for plugin function members of the group. +/// @fn { +/// :bullet_time_plugin, +/// #[cfg(feature = "external_forces")] +/// features:::force_debug_plugin, +/// #[doc(hidden)] +/// internal:::internal_plugin, +/// } /// } /// /// You may add doc comments after the plugin group as well. They will be appended after /// /// the documented list of plugins. @@ -128,6 +142,24 @@ macro_rules! plugin_group { $($hidden_plugin_path:ident::)* : $hidden_plugin_name:ident ),+ )? + $( + $(,)? @fn { + $( + $(#[cfg(feature = $fn_plugin_feature:literal)])? + $(#[custom($fn_plugin_meta:meta)])* + $($fn_plugin_path:ident::)* : $fn_plugin_name:ident + ),* + $( + $(,)?$( + #[doc(hidden)] + $(#[cfg(feature = $fn_hidden_plugin_feature:literal)])? + $(#[custom($fn_hidden_plugin_meta:meta)])* + $($fn_hidden_plugin_path:ident::)* : $fn_hidden_plugin_name:ident + ),+ + )? + $(,)? + } + )? $(,)? } @@ -143,6 +175,10 @@ macro_rules! plugin_group { " - [`", stringify!($plugin_group_name), "`](" $(, stringify!($plugin_group_path), "::")*, stringify!($plugin_group_name), ")" $(, " - with feature `", $plugin_group_feature, "`")? )])+)? + $($(#[doc = ::core::concat!( + " - [`", ::core::stringify!($fn_plugin_name), "`](" $(, ::core::stringify!($fn_plugin_path), "::")*, ::core::stringify!($fn_plugin_name), ")" + $(, " - with feature `", $fn_plugin_feature, "`")? + )])*)? $( /// $(#[doc = $post_doc])+ @@ -189,6 +225,20 @@ macro_rules! plugin_group { group = group.add(<$($hidden_plugin_path::)*$hidden_plugin_name>::default()); } )+)? + $($( + $(#[cfg(feature = $fn_plugin_feature)])? + $(#[$fn_plugin_meta])* + { + group = group.add($($fn_plugin_path::)*$fn_plugin_name); + } + )*)? + $($($( + $(#[cfg(feature = $fn_hidden_plugin_feature)])? + $(#[$fn_hidden_plugin_meta])* + { + group = group.add($($fn_hidden_plugin_path::)*$fn_hidden_plugin_name); + } + )+)?)? group } @@ -578,6 +628,9 @@ mod tests { fn build(&self, _: &mut App) {} } + fn plugin_d(_: &mut App) {} + fn plugin_e(_: &mut App) {} + #[derive(PartialEq, Debug)] struct PluginWithData(u32); impl Plugin for PluginWithData { @@ -901,4 +954,49 @@ mod tests { fn construct_nested_plugin_groups() { PluginGroupC {}.build(); } + plugin_group! { + #[derive(Default)] + struct PluginGroupD { + :PluginA + @fn { + #[doc(hidden)] + :plugin_d + } + } + } + plugin_group! { + #[derive(Default)] + struct PluginGroupE { + @fn { + :plugin_e + } + } + } + plugin_group! { + struct PluginGroupF { + :PluginB + #[plugin_group] + :PluginGroupD, + #[plugin_group] + :PluginGroupE, + } + } + #[test] + fn construct_nested_plugin_groups_with_plugin_functions() { + fn type_id_of(_: T) -> TypeId { + TypeId::of::() + } + + let group = PluginGroupF {}.build(); + + assert_eq!( + group.order, + vec![ + TypeId::of::(), + TypeId::of::(), + type_id_of(plugin_d), + type_id_of(plugin_e), + ] + ); + } }