diff --git a/crates/bevy_app/src/app.rs b/crates/bevy_app/src/app.rs index 63ce7d052d16e..450485d05db9e 100644 --- a/crates/bevy_app/src/app.rs +++ b/crates/bevy_app/src/app.rs @@ -68,6 +68,7 @@ pub struct App { /// A container of [`Stage`]s set to be run in a linear order. pub schedule: Schedule, sub_apps: HashMap, + plugin_registry: Vec>, } impl Debug for App { @@ -131,6 +132,7 @@ impl App { schedule: Default::default(), runner: Box::new(run_once), sub_apps: HashMap::default(), + plugin_registry: Vec::default(), } } @@ -825,11 +827,59 @@ impl App { where T: Plugin, { + self.add_boxed_plugin(Box::new(plugin)) + } + + /// Boxed variant of `add_plugin`, can be used from a [`PluginGroup`] + pub(crate) fn add_boxed_plugin(&mut self, plugin: Box) -> &mut Self { debug!("added plugin: {}", plugin.name()); plugin.build(self); + self.plugin_registry.push(plugin); self } + /// Checks if a [`Plugin`] has already been added. + /// + /// This can be used by plugins to check if a plugin they depend upon has already been + /// added. + pub fn is_plugin_added(&self) -> bool + where + T: Plugin, + { + self.plugin_registry + .iter() + .any(|p| p.downcast_ref::().is_some()) + } + + /// Returns a vector of references to any plugins of type `T` that have been added. + /// + /// This can be used to read the settings of any already added plugins. + /// This vector will be length zero if no plugins of that type have been added. + /// If multiple copies of the same plugin are added to the [`App`], they will be listed in insertion order in this vector. + /// + /// ```rust + /// # use bevy_app::prelude::*; + /// # #[derive(Default)] + /// # struct ImagePlugin { + /// # default_sampler: bool, + /// # } + /// # impl Plugin for ImagePlugin { + /// # fn build(&self, app: &mut App) {} + /// # } + /// # let mut app = App::new(); + /// # app.add_plugin(ImagePlugin::default()); + /// let default_sampler = app.get_added_plugins::()[0].default_sampler; + /// ``` + pub fn get_added_plugins(&self) -> Vec<&T> + where + T: Plugin, + { + self.plugin_registry + .iter() + .filter_map(|p| p.downcast_ref()) + .collect() + } + /// Adds a group of [`Plugin`]s. /// /// [`Plugin`]s can be grouped into a set by using a [`PluginGroup`]. diff --git a/crates/bevy_app/src/plugin_group.rs b/crates/bevy_app/src/plugin_group.rs index 91e6773b48d98..476e2890fb78f 100644 --- a/crates/bevy_app/src/plugin_group.rs +++ b/crates/bevy_app/src/plugin_group.rs @@ -155,12 +155,12 @@ impl PluginGroupBuilder { /// Consumes the [`PluginGroupBuilder`] and [builds](Plugin::build) the contained [`Plugin`]s /// in the order specified. - pub fn finish(self, app: &mut App) { + pub fn finish(mut self, app: &mut App) { for ty in &self.order { - if let Some(entry) = self.plugins.get(ty) { + if let Some(entry) = self.plugins.remove(ty) { if entry.enabled { debug!("added plugin: {}", entry.plugin.name()); - entry.plugin.build(app); + app.add_boxed_plugin(entry.plugin); } } }