use crate::{Entity, State};
use std::any::{Any, TypeId};
use std::fmt::Debug;
#[derive(Debug, Clone, PartialEq)]
pub enum Propagation {
Down,
Up,
DownUp,
Fall,
Direct,
All,
}
pub trait Message: Any {
fn as_any(&self) -> &dyn Any;
fn equals_a(&self, _: &dyn Message) -> bool;
}
impl dyn Message {
pub fn is<T: Message>(&self) -> bool {
let t = TypeId::of::<T>();
let concrete = self.type_id();
t == concrete
}
pub fn downcast<T>(&mut self) -> Option<&mut T>
where
T: Message,
{
if self.is::<T>() {
unsafe { Some(&mut *(self as *mut dyn Message as *mut T)) }
} else {
None
}
}
}
impl<S: 'static + PartialEq> Message for S {
fn as_any(&self) -> &dyn Any {
self
}
fn equals_a(&self, other: &dyn Message) -> bool {
other
.as_any()
.downcast_ref::<S>()
.map_or(false, |a| self == a)
}
}
pub struct Event {
pub origin: Entity,
pub target: Entity,
pub propagation: Propagation,
pub consumable: bool,
pub(crate) consumed: bool,
pub unique: bool,
pub order: i32,
pub message: Box<dyn Message>,
}
impl PartialEq for Event {
fn eq(&self, other: &Event) -> bool {
self.message.equals_a(&*other.message)
&& self.target == other.target
}
}
impl Event {
pub fn new<M>(message: M) -> Self
where
M: Message,
{
Event {
origin: Entity::null(),
target: Entity::null(),
propagation: Propagation::Up,
consumable: true,
consumed: false,
unique: true,
order: 0,
message: Box::new(message),
}
}
pub fn target(mut self, entity: Entity) -> Self {
self.target = entity;
self
}
pub fn origin(mut self, entity: Entity) -> Self {
self.origin = entity;
self
}
pub fn unique(mut self) -> Self {
self.unique = true;
self
}
pub fn propagate(mut self, propagation: Propagation) -> Self {
self.propagation = propagation;
self
}
pub fn direct(mut self, entity: Entity) -> Self {
self.propagation = Propagation::Direct;
self.target = entity;
self
}
pub fn consume(&mut self) {
self.consumed = true;
}
}