use crate::{
component::ComponentId,
entity::Entity,
event::Event,
world::{Command, DeferredWorld, World},
};
pub struct TriggerEvent<E, Targets: TriggerTargets = ()> {
pub event: E,
pub targets: Targets,
}
impl<E: Event, Targets: TriggerTargets> Command for TriggerEvent<E, Targets> {
fn apply(mut self, world: &mut World) {
let event_type = world.init_component::<E>();
trigger_event(world, event_type, &mut self.event, self.targets);
}
}
pub struct EmitDynamicTrigger<T, Targets: TriggerTargets = ()> {
event_type: ComponentId,
event_data: T,
targets: Targets,
}
impl<E, Targets: TriggerTargets> EmitDynamicTrigger<E, Targets> {
pub unsafe fn new_with_id(event_type: ComponentId, event_data: E, targets: Targets) -> Self {
Self {
event_type,
event_data,
targets,
}
}
}
impl<E: Event, Targets: TriggerTargets> Command for EmitDynamicTrigger<E, Targets> {
fn apply(mut self, world: &mut World) {
trigger_event(world, self.event_type, &mut self.event_data, self.targets);
}
}
#[inline]
fn trigger_event<E, Targets: TriggerTargets>(
world: &mut World,
event_type: ComponentId,
event_data: &mut E,
targets: Targets,
) {
let mut world = DeferredWorld::from(world);
if targets.entities().len() == 0 {
unsafe {
world.trigger_observers_with_data(
event_type,
Entity::PLACEHOLDER,
targets.components(),
event_data,
);
};
} else {
for target in targets.entities() {
unsafe {
world.trigger_observers_with_data(
event_type,
target,
targets.components(),
event_data,
);
};
}
}
}
pub trait TriggerTargets: Send + Sync + 'static {
fn components(&self) -> impl ExactSizeIterator<Item = ComponentId>;
fn entities(&self) -> impl ExactSizeIterator<Item = Entity>;
}
impl TriggerTargets for () {
fn components(&self) -> impl ExactSizeIterator<Item = ComponentId> {
[].into_iter()
}
fn entities(&self) -> impl ExactSizeIterator<Item = Entity> {
[].into_iter()
}
}
impl TriggerTargets for Entity {
fn components(&self) -> impl ExactSizeIterator<Item = ComponentId> {
[].into_iter()
}
fn entities(&self) -> impl ExactSizeIterator<Item = Entity> {
std::iter::once(*self)
}
}
impl TriggerTargets for Vec<Entity> {
fn components(&self) -> impl ExactSizeIterator<Item = ComponentId> {
[].into_iter()
}
fn entities(&self) -> impl ExactSizeIterator<Item = Entity> {
self.iter().copied()
}
}
impl<const N: usize> TriggerTargets for [Entity; N] {
fn components(&self) -> impl ExactSizeIterator<Item = ComponentId> {
[].into_iter()
}
fn entities(&self) -> impl ExactSizeIterator<Item = Entity> {
self.iter().copied()
}
}
impl TriggerTargets for ComponentId {
fn components(&self) -> impl ExactSizeIterator<Item = ComponentId> {
std::iter::once(*self)
}
fn entities(&self) -> impl ExactSizeIterator<Item = Entity> {
[].into_iter()
}
}
impl TriggerTargets for Vec<ComponentId> {
fn components(&self) -> impl ExactSizeIterator<Item = ComponentId> {
self.iter().copied()
}
fn entities(&self) -> impl ExactSizeIterator<Item = Entity> {
[].into_iter()
}
}
impl<const N: usize> TriggerTargets for [ComponentId; N] {
fn components(&self) -> impl ExactSizeIterator<Item = ComponentId> {
self.iter().copied()
}
fn entities(&self) -> impl ExactSizeIterator<Item = Entity> {
[].into_iter()
}
}