use std::any::Any; use anyhow::Result; use ecs::World; use super::ControllerButton; macro_rules! callbacks { ($name:ident, $($cb:tt)*) => { #[derive(Default)] pub struct $name<'a> { callbacks: Vec<(&'a str, Box)>, } impl<'a> $name<'a> { pub fn add(mut self, name: &'a str, callback: impl $($cb)* + 'static)->Self { self.callbacks.push((name, Box::new(callback))); self } } impl<'a> Into)>> for $name<'a> { fn into(self) -> Vec<(&'a str, Box)> { self.callbacks } } }; } callbacks!(ClickCallbacks, Fn(&mut World) -> Result<()> + Send + Sync); callbacks!(SelectCallbacks, Fn(&mut World, bool) -> anyhow::Result<()> + Send + Sync); callbacks!(CustomCallbacks, Fn(&mut World, ControllerButton) -> anyhow::Result + Send + Sync); callbacks!( VecCallbacks, Fn(&mut World, &dyn Any) -> Result<()> + Send + Sync ); #[cfg(test)] mod test { use super::*; use anyhow::Result; fn normal_fn() -> impl Fn(&mut World) -> Result<()> + Send + Sync { |_| Ok(()) } #[test] fn test_click_callback_builder() { struct Test; impl Test { fn set_click_callbacks( &self, _callbacks: Vec<(&str, Box Result<()> + Send + Sync>)>, ) -> Result<()> { Ok(()) } } let t = Test; let cbs = ClickCallbacks::default().add("normal_test", normal_fn()); t.set_click_callbacks(cbs.into()).unwrap(); } }