use crate::classes::Object;
use crate::obj::{Gd, GodotClass, WithBaseField, WithSignals, WithUserSignals};
#[doc(hidden)]
pub trait SignalObject<'c> {
fn with_object_mut(&mut self, f: impl FnOnce(&mut Object));
fn to_owned_object(&self) -> Gd<Object>;
}
#[doc(hidden)]
pub enum UserSignalObject<'c, C> {
Internal { self_mut: &'c mut C },
External { gd: Gd<Object> },
}
impl<'c, C> UserSignalObject<'c, C>
where
C: WithUserSignals + WithSignals<__SignalObj<'c> = UserSignalObject<'c, C>>,
{
#[inline]
pub fn from_external(object: Gd<C>) -> Self {
Self::External {
gd: object.upcast(),
}
}
#[inline]
pub fn from_internal(self_mut: &'c mut C) -> Self {
Self::Internal { self_mut }
}
}
impl<'c, C: WithUserSignals> SignalObject<'c> for UserSignalObject<'c, C> {
#[inline]
fn with_object_mut(&mut self, f: impl FnOnce(&mut Object)) {
match self {
Self::Internal { self_mut } => {
let mut guard = <C as WithBaseField>::base_mut(*self_mut);
f(guard.upcast_object_mut())
}
Self::External { gd } => f(gd.upcast_object_mut()),
}
}
#[inline]
fn to_owned_object(&self) -> Gd<Object> {
match self {
Self::Internal { self_mut } => <C as WithBaseField>::to_gd(self_mut).upcast_object(),
Self::External { gd } => gd.clone(),
}
}
}
impl<C: WithSignals> SignalObject<'_> for Gd<C> {
#[inline]
fn with_object_mut(&mut self, f: impl FnOnce(&mut Object)) {
f(self.upcast_object_mut())
}
#[inline]
fn to_owned_object(&self) -> Gd<Object> {
self.clone().upcast_object()
}
}
pub fn signal_collection_to_base<'r, 'c, C, Derived>(
derived: &'r Derived::SignalCollection<'c, C>,
) -> &'r <<Derived as GodotClass>::Base as WithSignals>::SignalCollection<'c, C>
where
C: WithSignals,
Derived: WithSignals<Base: WithSignals>,
{
type BaseCollection<'c, C, Derived> =
<<Derived as GodotClass>::Base as WithSignals>::SignalCollection<'c, C>;
let derived_collection_ptr = std::ptr::from_ref(derived);
let base_collection_ptr = derived_collection_ptr.cast::<BaseCollection<'c, C, Derived>>();
unsafe { &*base_collection_ptr }
}
pub fn signal_collection_to_base_mut<'r, 'c, C, Derived>(
derived: &'r mut Derived::SignalCollection<'c, C>,
) -> &'r mut <<Derived as GodotClass>::Base as WithSignals>::SignalCollection<'c, C>
where
C: WithSignals,
Derived: WithSignals<Base: WithSignals>,
{
type BaseCollection<'c, C, Derived> =
<<Derived as GodotClass>::Base as WithSignals>::SignalCollection<'c, C>;
let derived_collection_ptr = std::ptr::from_mut(derived);
let base_collection_ptr = derived_collection_ptr.cast::<BaseCollection<'c, C, Derived>>();
unsafe { &mut *base_collection_ptr }
}