use crate::{AppBuilder, Plugin}; use bevy_utils::{tracing::debug, HashMap}; use std::any::TypeId; pub trait PluginGroup { fn build(&mut self, group: &mut PluginGroupBuilder); } struct PluginEntry { plugin: Box, enabled: bool, } #[derive(Default)] pub struct PluginGroupBuilder { plugins: HashMap, order: Vec, } impl PluginGroupBuilder { pub fn add(&mut self, plugin: T) -> &mut Self { self.order.push(TypeId::of::()); self.plugins.insert( TypeId::of::(), PluginEntry { plugin: Box::new(plugin), enabled: true, }, ); self } pub fn add_before(&mut self, plugin: T) -> &mut Self { let target_index = self .order .iter() .enumerate() .find(|(_i, ty)| **ty == TypeId::of::()) .map(|(i, _)| i) .unwrap_or_else(|| { panic!("Plugin does not exist: {}", std::any::type_name::()) }); self.order.insert(target_index, TypeId::of::()); self.plugins.insert( TypeId::of::(), PluginEntry { plugin: Box::new(plugin), enabled: true, }, ); self } pub fn add_after(&mut self, plugin: T) -> &mut Self { let target_index = self .order .iter() .enumerate() .find(|(_i, ty)| **ty == TypeId::of::()) .map(|(i, _)| i) .unwrap_or_else(|| { panic!("Plugin does not exist: {}", std::any::type_name::()) }); self.order.insert(target_index + 1, TypeId::of::()); self.plugins.insert( TypeId::of::(), PluginEntry { plugin: Box::new(plugin), enabled: true, }, ); self } pub fn enable(&mut self) -> &mut Self { let mut plugin_entry = self .plugins .get_mut(&TypeId::of::()) .expect("Cannot enable a plugin that does not exist"); plugin_entry.enabled = true; self } pub fn disable(&mut self) -> &mut Self { let mut plugin_entry = self .plugins .get_mut(&TypeId::of::()) .expect("Cannot disable a plugin that does not exist"); plugin_entry.enabled = false; self } pub fn finish(self, app: &mut AppBuilder) { for ty in self.order.iter() { if let Some(entry) = self.plugins.get(ty) { if entry.enabled { debug!("added plugin: {}", entry.plugin.name()); entry.plugin.build(app); } } } } }