#![doc = include_str!("../README.md")]
use bevy::ecs::component::{ComponentId, Components};
use bevy::ecs::relationship::{Relationship, RelationshipSourceCollection};
use bevy::ecs::system::SystemParam;
use bevy::prelude::*;
pub use crate::trigger::EntityComponentTrigger;
pub use bevy_event_chain_derive::{ChainEvent, RelatedChainEvent};
mod trigger;
#[derive(Clone, Debug, Reflect)]
pub struct EventChain {
target: Entity,
target_index: usize,
targets: Vec<Entity>,
}
impl EventChain {
pub fn new(targets: Vec<Entity>) -> Self {
Self {
target: targets[0],
target_index: 0,
targets,
}
}
pub fn new_with_end(mut targets: Vec<Entity>, end: Entity) -> Self {
targets.push(end);
Self::new(targets)
}
pub fn next(&self) -> Self {
Self {
target: self.targets[self.target_index + 1],
target_index: self.target_index + 1,
targets: self.targets.clone(),
}
}
pub fn event_target(&self) -> Entity {
self.target
}
pub fn event_target_mut(&mut self) -> &mut Entity {
&mut self.target
}
pub fn reversed(&self) -> Self {
let target_index = self.targets.len() - self.target_index - 1;
let mut targets = self.targets.clone();
targets.reverse();
Self {
target: targets[target_index],
target_index,
targets,
}
}
}
pub trait ChainEvent: EntityEvent + Clone {
fn next(&self) -> Self;
}
#[derive(Clone, Debug, Reflect)]
pub struct RelatedEventChain {
chain: EventChain,
relationship_target: ComponentId,
relationship: ComponentId,
}
impl RelatedEventChain {
pub fn next(&self) -> Self {
Self {
chain: self.chain.next(),
relationship_target: self.relationship_target,
relationship: self.relationship,
}
}
pub fn get_trigger(&self) -> EntityComponentTrigger {
if self.chain.target_index + 1 == self.chain.targets.len() {
EntityComponentTrigger {
component: self.relationship_target,
}
} else {
EntityComponentTrigger {
component: self.relationship,
}
}
}
pub fn event_target(&self) -> Entity {
self.chain.event_target()
}
pub fn event_target_mut(&mut self) -> &mut Entity {
self.chain.event_target_mut()
}
pub fn reversed(&self) -> Self {
let mut chain = self.chain.reversed();
let rel_target = chain.targets.remove(0);
chain.targets.push(rel_target);
Self {
chain,
relationship_target: self.relationship_target,
relationship: self.relationship,
}
}
}
pub trait RelatedChainEvent:
for<'a> Event<Trigger<'a> = EntityComponentTrigger> + EntityEvent + Clone
{
type Relationship: Relationship<RelationshipTarget = Self::RelationshipTarget>;
type RelationshipTarget: RelationshipTarget<Relationship = Self::Relationship>;
fn next(&self) -> Self;
fn get_trigger(&self) -> EntityComponentTrigger;
fn trigger(self, commands: &mut Commands) {
let this_trigger = self.get_trigger();
commands.trigger_with(self, this_trigger);
}
fn trigger_next(&self, commands: &mut Commands) {
self.next().trigger(commands);
}
}
#[derive(SystemParam)]
pub struct ChainEventRelation<'w, 's, Event: RelatedChainEvent> {
relation: Query<'w, 's, &'static <Event as RelatedChainEvent>::RelationshipTarget>,
components: &'w Components,
}
impl<'w, 's, Event: RelatedChainEvent> ChainEventRelation<'w, 's, Event> {
pub fn new_chain(&self, relationship_target: Entity) -> RelatedEventChain {
let targets = self
.relation
.get(relationship_target)
.unwrap() .collection()
.iter()
.chain([relationship_target])
.collect::<Vec<_>>();
RelatedEventChain {
chain: EventChain::new(targets),
relationship_target: self
.components
.component_id::<Event::RelationshipTarget>()
.unwrap(), relationship: self
.components
.component_id::<Event::Relationship>()
.unwrap(),
}
}
}