mod signal_component;
mod signal_utils;
use std::{any::type_name, sync::Arc};
pub use async_shared::Value;
use bevy::ecs::{event::EntityEvent, observer::On, world::World};
pub use signal_component::{SignalMap, Signals};
pub use signal_utils::*;
use crate::{
access::{get_entity::VirtualEntity, AsyncEntity},
executor::with_world_mut,
AccessError, AccessResult,
};
impl<E: VirtualEntity> AsyncEntity<E> {
pub fn send_signal<S: SignalId>(&self, data: S::Data) -> AccessResult<bool> {
with_world_mut(move |world: &mut World| {
let entity = self.0.try_get_entity(world)?;
let Ok(mut entity) = world.get_entity_mut(entity) else {
return Err(AccessError::EntityNotFound(entity));
};
let Some(signals) = entity.get_mut::<Signals>() else {
return Err(AccessError::ComponentNotFound {
entity: entity.id(),
name: type_name::<S>(),
});
};
Ok(signals.send::<S>(data))
})
}
pub fn signal_sender<S: SignalId>(&self) -> AccessResult<Arc<Value<S::Data>>> {
with_world_mut(move |world: &mut World| {
let entity = self.0.try_get_entity(world)?;
let Ok(mut entity) = world.get_entity_mut(entity) else {
return Err(AccessError::EntityNotFound(entity));
};
let mut signals = match entity.get_mut::<Signals>() {
Some(sender) => sender,
None => entity.insert(Signals::new()).get_mut::<Signals>().unwrap(),
};
Ok(signals.init_sender::<S>())
})
}
pub fn signal_receiver<S: SignalId>(&self) -> AccessResult<Arc<Value<S::Data>>> {
with_world_mut(move |world: &mut World| {
let entity = self.0.try_get_entity(world)?;
let Ok(mut entity) = world.get_entity_mut(entity) else {
return Err(AccessError::EntityNotFound(entity));
};
let mut signals = match entity.get_mut::<Signals>() {
Some(sender) => sender,
None => entity.insert(Signals::new()).get_mut::<Signals>().unwrap(),
};
Ok(signals.init_receiver::<S>())
})
}
pub fn signal_observe<T: EntityEvent + Clone>(&self) -> AccessResult {
let signal = self.signal_receiver::<Observed<T>>()?;
with_world_mut(|world| {
let entity = self.0.try_get_entity(world)?;
world.entity_mut(entity).observe(move |trigger: On<T>| {
signal.write(trigger.event().clone());
});
Ok(())
})?;
Ok(())
}
}