bevy_ecs/observer/
trigger_event.rsuse 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> TriggerEvent<E, Targets> {
pub(super) fn trigger(mut self, world: &mut World) {
let event_type = world.register_component::<E>();
trigger_event(world, event_type, &mut self.event, self.targets);
}
}
impl<E: Event, Targets: TriggerTargets> TriggerEvent<&mut E, Targets> {
pub(super) fn trigger_ref(self, world: &mut World) {
let event_type = world.register_component::<E>();
trigger_event(world, event_type, self.event, self.targets);
}
}
impl<E: Event, Targets: TriggerTargets + Send + Sync + 'static> Command
for TriggerEvent<E, Targets>
{
fn apply(self, world: &mut World) {
self.trigger(world);
}
}
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 + Send + Sync + 'static> 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: Event, Targets: TriggerTargets>(
world: &mut World,
event_type: ComponentId,
event_data: &mut E,
targets: Targets,
) {
let mut world = DeferredWorld::from(world);
if targets.entities().is_empty() {
unsafe {
world.trigger_observers_with_data::<_, E::Traversal>(
event_type,
Entity::PLACEHOLDER,
targets.components(),
event_data,
false,
);
};
} else {
for target in targets.entities() {
unsafe {
world.trigger_observers_with_data::<_, E::Traversal>(
event_type,
*target,
targets.components(),
event_data,
E::AUTO_PROPAGATE,
);
};
}
}
}
pub trait TriggerTargets {
fn components(&self) -> &[ComponentId];
fn entities(&self) -> &[Entity];
}
impl TriggerTargets for () {
fn components(&self) -> &[ComponentId] {
&[]
}
fn entities(&self) -> &[Entity] {
&[]
}
}
impl TriggerTargets for Entity {
fn components(&self) -> &[ComponentId] {
&[]
}
fn entities(&self) -> &[Entity] {
core::slice::from_ref(self)
}
}
impl TriggerTargets for Vec<Entity> {
fn components(&self) -> &[ComponentId] {
&[]
}
fn entities(&self) -> &[Entity] {
self.as_slice()
}
}
impl<const N: usize> TriggerTargets for [Entity; N] {
fn components(&self) -> &[ComponentId] {
&[]
}
fn entities(&self) -> &[Entity] {
self.as_slice()
}
}
impl TriggerTargets for ComponentId {
fn components(&self) -> &[ComponentId] {
core::slice::from_ref(self)
}
fn entities(&self) -> &[Entity] {
&[]
}
}
impl TriggerTargets for Vec<ComponentId> {
fn components(&self) -> &[ComponentId] {
self.as_slice()
}
fn entities(&self) -> &[Entity] {
&[]
}
}
impl<const N: usize> TriggerTargets for [ComponentId; N] {
fn components(&self) -> &[ComponentId] {
self.as_slice()
}
fn entities(&self) -> &[Entity] {
&[]
}
}
impl TriggerTargets for &Vec<Entity> {
fn components(&self) -> &[ComponentId] {
&[]
}
fn entities(&self) -> &[Entity] {
self.as_slice()
}
}