use std::marker::PhantomData;
use crate::meta::{FromGodot, InParamTuple};
use crate::obj::{Gd, GodotClass};
pub trait SignalReceiver<C, Ps>: 'static {
fn call(&mut self, maybe_instance: C, params: Ps);
}
pub struct IndirectSignalReceiver<'view, C, Ps, F>
where
Ps: InParamTuple,
F: SignalReceiver<C, Ps> + 'static,
{
inner: &'view mut F,
_phantoms: PhantomData<(C, Ps)>,
}
impl<'view, C, Ps, F> IndirectSignalReceiver<'view, C, Ps, F>
where
Ps: InParamTuple,
F: SignalReceiver<C, Ps> + 'static,
{
pub fn function(&'view mut self) -> &'view mut F {
self.inner
}
fn new(inner: &'view mut F) -> Self {
Self {
inner,
_phantoms: PhantomData,
}
}
}
macro_rules! impl_signal_recipient {
($( #[$attr:meta] )? $( $args:ident : $Ps:ident ),*) => {
$( #[$attr] )?
impl<F, R, $($Ps: std::fmt::Debug + FromGodot + 'static),*> SignalReceiver<(), ( $($Ps,)* )> for F
where F: FnMut( $($Ps,)* ) -> R + 'static
{
fn call(&mut self, _no_instance: (), ($($args,)*): ( $($Ps,)* )) {
self($($args,)*);
}
}
$( #[$attr] )?
impl<F, R, C, $($Ps: std::fmt::Debug + FromGodot + 'static),*> SignalReceiver<&mut C, ( $($Ps,)* )> for F
where F: FnMut( &mut C, $($Ps,)* ) -> R + 'static
{
fn call(&mut self, instance: &mut C, ($($args,)*): ( $($Ps,)* )) {
self(instance, $($args,)*);
}
}
$( #[$attr] )?
impl<F, R, C, $($Ps: std::fmt::Debug + FromGodot + 'static),*> SignalReceiver<Gd<C>, ( $($Ps,)* )> for F
where F: FnMut( Gd<C>, $($Ps,)* ) -> R + 'static, C: GodotClass
{
fn call(&mut self, instance: Gd<C>, ($($args,)*): ( $($Ps,)* )) {
self(instance, $($args,)*);
}
}
$( #[$attr] )?
impl<'c_view, F, R, $($Ps: std::fmt::Debug + FromGodot + 'static),*>
From<&'c_view mut F> for IndirectSignalReceiver<'c_view, (), ($($Ps,)*), F>
where F: FnMut( $($Ps,)* ) -> R + 'static
{
fn from(value: &'c_view mut F) -> Self {
IndirectSignalReceiver::new(value)
}
}
$( #[$attr] )?
impl<'c_view, F, R, C, $($Ps: std::fmt::Debug + FromGodot + 'static),*>
From<&'c_view mut F> for IndirectSignalReceiver<'c_view, &mut C, ($($Ps,)*), F>
where F: FnMut( &mut C, $($Ps,)* ) -> R + 'static
{
fn from(value: &'c_view mut F) -> Self {
IndirectSignalReceiver::new(value)
}
}
$( #[$attr] )?
impl<'c_view, F, R, C, $($Ps: std::fmt::Debug + FromGodot + 'static),*>
From<&'c_view mut F> for IndirectSignalReceiver<'c_view, Gd<C>, ($($Ps,)*), F>
where F: FnMut( Gd<C>, $($Ps,)* ) -> R + 'static, C: GodotClass
{
fn from(value: &'c_view mut F) -> Self {
IndirectSignalReceiver::new(value)
}
}
};
}
impl_signal_recipient!(#[doc(hidden)] );
impl_signal_recipient!(#[doc(hidden)] arg0: P0);
impl_signal_recipient!(#[doc(hidden)] arg0: P0, arg1: P1);
impl_signal_recipient!( arg0: P0, arg1: P1, arg2: P2);
impl_signal_recipient!(#[doc(hidden)] arg0: P0, arg1: P1, arg2: P2, arg3: P3);
impl_signal_recipient!(#[doc(hidden)] arg0: P0, arg1: P1, arg2: P2, arg3: P3, arg4: P4);
impl_signal_recipient!(#[doc(hidden)] arg0: P0, arg1: P1, arg2: P2, arg3: P3, arg4: P4, arg5: P5);
impl_signal_recipient!(#[doc(hidden)] arg0: P0, arg1: P1, arg2: P2, arg3: P3, arg4: P4, arg5: P5, arg6: P6);
impl_signal_recipient!(#[doc(hidden)] arg0: P0, arg1: P1, arg2: P2, arg3: P3, arg4: P4, arg5: P5, arg6: P6, arg7: P7);
impl_signal_recipient!(#[doc(hidden)] arg0: P0, arg1: P1, arg2: P2, arg3: P3, arg4: P4, arg5: P5, arg6: P6, arg7: P7, arg8: P8);
impl_signal_recipient!(#[doc(hidden)] arg0: P0, arg1: P1, arg2: P2, arg3: P3, arg4: P4, arg5: P5, arg6: P6, arg7: P7, arg8: P8, arg9: P9);