use super::signal_component::Signals;
use std::{any::Any, marker::PhantomData};
pub trait SignalId: Any + Send + Sync + 'static {
type Data: Send + Sync + Clone + 'static;
}
#[macro_export]
macro_rules! signal_ids {
($($(#[$($attr:tt)*])*$vis: vis $name: ident: $ty: ty),* $(,)?) => {
$(
$(#[$($attr)*])*
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
$vis enum $name {}
impl $crate::signals::SignalId for $name{
type Data = $ty;
}
)*
};
}
pub struct Fac<T: Clone + Default + Send + Sync + 'static>(
PhantomData<T>,
std::convert::Infallible,
);
impl<T: Clone + Default + Send + Sync + 'static> SignalId for Fac<T> {
type Data = T;
}
pub struct Observed<T: Clone + Event>(PhantomData<T>, std::convert::Infallible);
impl<T: Clone + Event> SignalId for Observed<T> {
type Data = T;
}
mod sealed {
use std::marker::PhantomData;
use bevy::ecs::query::QueryData;
use super::{SignalId, Signals};
#[derive(Debug, QueryData)]
pub struct SignalSender<T: SignalId> {
signals: Option<&'static Signals>,
p: PhantomData<T>,
}
impl<T: SignalId> SignalSenderItem<'_, '_, T> {
pub fn exists(&self) -> bool {
self.signals
.map(|x| x.borrow_sender::<T>().is_some())
.unwrap_or(false)
}
pub fn send(&self, item: T::Data) -> bool {
if let Some(signals) = self.signals {
signals.send::<T>(item)
} else {
false
}
}
pub fn send_if_changed(&self, item: T::Data) -> bool
where
T::Data: PartialEq,
{
if let Some(signals) = self.signals {
signals.send_if_changed::<T>(item)
} else {
false
}
}
pub fn broadcast(&self, item: T::Data) -> bool {
if let Some(signals) = self.signals {
signals.broadcast::<T>(item)
} else {
false
}
}
pub fn poll_sender(&self) -> Option<T::Data> {
self.signals.and_then(|s| s.poll_sender_once::<T>())
}
}
#[derive(Debug, QueryData)]
pub struct SignalReceiver<T: SignalId> {
signals: Option<&'static Signals>,
p: PhantomData<T>,
}
impl<T: SignalId> SignalReceiverItem<'_, '_, T> {
pub fn poll_once(&self) -> Option<T::Data> {
self.signals.as_ref().and_then(|sig| sig.poll_once::<T>())
}
pub fn poll_change(&self) -> bool {
self.signals
.as_ref()
.and_then(|sig| sig.poll_once::<T>())
.is_some()
}
}
}
use bevy::ecs::event::Event;
pub use sealed::{SignalReceiver, SignalSender};