use alloc::vec::Vec;
use itertools::Itertools;
use crate::{
archetype::{Archetype, Slice, Storage},
component::{ComponentDesc, ComponentKey, ComponentValue},
filter::StaticFilter,
sink::Sink,
Component, Entity,
};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Event {
pub id: Entity,
pub key: ComponentKey,
pub kind: EventKind,
}
impl Event {
pub fn new(id: Entity, key: ComponentKey, kind: EventKind) -> Self {
Self { id, key, kind }
}
pub fn modified(id: Entity, key: ComponentKey) -> Self {
Self::new(id, key, EventKind::Modified)
}
pub fn added(id: Entity, key: ComponentKey) -> Self {
Self::new(id, key, EventKind::Added)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum EventKind {
Added,
Removed,
Modified,
}
pub struct EventData<'a> {
pub ids: &'a [Entity],
pub slots: Slice,
pub key: ComponentKey,
}
pub trait EventSubscriber: ComponentValue {
fn on_added(&self, storage: &Storage, event: &EventData);
fn on_modified(&self, event: &EventData);
fn on_removed(&self, storage: &Storage, event: &EventData);
fn is_connected(&self) -> bool;
#[inline]
fn matches_arch(&self, _: &Archetype) -> bool {
true
}
#[inline]
fn matches_component(&self, _: ComponentDesc) -> bool {
true
}
fn filter<F>(self, func: F) -> FilterFunc<Self, F>
where
Self: Sized,
F: Fn(EventKind, &EventData) -> bool,
{
FilterFunc {
subscriber: self,
filter: func,
}
}
fn filter_arch<F: StaticFilter>(self, filter: F) -> FilterArch<Self, F>
where
Self: Sized,
{
FilterArch {
filter,
subscriber: self,
}
}
fn filter_components<I: IntoIterator<Item = ComponentKey>>(
self,
components: I,
) -> FilterComponents<Self>
where
Self: Sized,
{
FilterComponents {
components: components.into_iter().collect(),
subscriber: self,
}
}
fn filter_event_kind(self, event_kind: EventKind) -> FilterEventKind<Self>
where
Self: Sized,
{
FilterEventKind {
event_kind,
subscriber: self,
}
}
}
impl<S> EventSubscriber for S
where
S: 'static + Send + Sync + Sink<Event>,
{
fn on_added(&self, _: &Storage, event: &EventData) {
for &id in event.ids {
self.send(Event {
id,
key: event.key,
kind: EventKind::Added,
});
}
}
fn on_modified(&self, event: &EventData) {
for &id in event.ids {
self.send(Event {
id,
key: event.key,
kind: EventKind::Modified,
});
}
}
fn on_removed(&self, _: &Storage, event: &EventData) {
for &id in event.ids {
self.send(Event {
id,
key: event.key,
kind: EventKind::Removed,
});
}
}
fn is_connected(&self) -> bool {
<Self as Sink<Event>>::is_connected(self)
}
}
pub struct WithValue<T, S> {
component: Component<T>,
sink: S,
}
impl<T, S> WithValue<T, S> {
pub fn new(component: Component<T>, sink: S) -> Self {
Self { component, sink }
}
}
impl<T: ComponentValue + Clone, S: 'static + Send + Sync + Sink<(Event, T)>> EventSubscriber
for WithValue<T, S>
{
fn on_added(&self, storage: &Storage, event: &EventData) {
let values = storage.downcast_ref::<T>();
for (&id, slot) in event.ids.iter().zip_eq(event.slots.as_range()) {
let value = values[slot].clone();
self.sink.send((
Event {
id,
key: event.key,
kind: EventKind::Added,
},
value,
));
}
}
fn on_modified(&self, _: &EventData) {}
fn on_removed(&self, storage: &Storage, event: &EventData) {
let values = storage.downcast_ref::<T>();
for (&id, slot) in event.ids.iter().zip_eq(event.slots.as_range()) {
let value = values[slot].clone();
self.sink.send((
Event {
id,
key: event.key,
kind: EventKind::Removed,
},
value,
));
}
}
fn is_connected(&self) -> bool {
self.sink.is_connected()
}
fn matches_component(&self, desc: ComponentDesc) -> bool {
self.component.desc() == desc
}
fn matches_arch(&self, arch: &Archetype) -> bool {
arch.has(self.component.key())
}
}
pub struct FilterArch<S, F> {
filter: F,
subscriber: S,
}
impl<S, F> EventSubscriber for FilterArch<S, F>
where
S: EventSubscriber,
F: ComponentValue + StaticFilter,
{
fn on_added(&self, storage: &Storage, event: &EventData) {
self.subscriber.on_added(storage, event)
}
fn on_modified(&self, event: &EventData) {
self.subscriber.on_modified(event);
}
fn on_removed(&self, storage: &Storage, event: &EventData) {
self.subscriber.on_removed(storage, event)
}
#[inline]
fn is_connected(&self) -> bool {
self.subscriber.is_connected()
}
#[inline]
fn matches_arch(&self, arch: &Archetype) -> bool {
self.filter.filter_static(arch) && self.subscriber.matches_arch(arch)
}
#[inline]
fn matches_component(&self, desc: ComponentDesc) -> bool {
self.subscriber.matches_component(desc)
}
}
pub struct FilterFunc<S, F> {
filter: F,
subscriber: S,
}
impl<S, F> EventSubscriber for FilterFunc<S, F>
where
S: EventSubscriber,
F: ComponentValue + Fn(EventKind, &EventData) -> bool,
{
fn on_added(&self, storage: &Storage, event: &EventData) {
if (self.filter)(EventKind::Added, event) {
self.subscriber.on_added(storage, event)
}
}
fn on_modified(&self, event: &EventData) {
if (self.filter)(EventKind::Modified, event) {
self.subscriber.on_modified(event)
}
}
fn on_removed(&self, storage: &Storage, event: &EventData) {
if (self.filter)(EventKind::Removed, event) {
self.subscriber.on_removed(storage, event)
}
}
#[inline]
fn matches_arch(&self, arch: &Archetype) -> bool {
self.subscriber.matches_arch(arch)
}
#[inline]
fn matches_component(&self, desc: ComponentDesc) -> bool {
self.subscriber.matches_component(desc)
}
#[inline]
fn is_connected(&self) -> bool {
self.subscriber.is_connected()
}
}
pub struct FilterComponents<S> {
components: Vec<ComponentKey>,
subscriber: S,
}
impl<S> EventSubscriber for FilterComponents<S>
where
S: EventSubscriber,
{
fn on_added(&self, storage: &Storage, event: &EventData) {
self.subscriber.on_added(storage, event)
}
fn on_modified(&self, event: &EventData) {
self.subscriber.on_modified(event)
}
fn on_removed(&self, storage: &Storage, event: &EventData) {
self.subscriber.on_removed(storage, event)
}
#[inline]
fn matches_arch(&self, arch: &Archetype) -> bool {
self.components.iter().any(|&key| arch.has(key)) && self.subscriber.matches_arch(arch)
}
#[inline]
fn matches_component(&self, desc: ComponentDesc) -> bool {
self.components.contains(&desc.key()) && self.subscriber.matches_component(desc)
}
#[inline]
fn is_connected(&self) -> bool {
self.subscriber.is_connected()
}
}
pub struct FilterEventKind<S> {
event_kind: EventKind,
subscriber: S,
}
impl<S> EventSubscriber for FilterEventKind<S>
where
S: EventSubscriber,
{
fn on_added(&self, storage: &Storage, event: &EventData) {
if self.event_kind == EventKind::Added {
self.subscriber.on_added(storage, event)
}
}
fn on_modified(&self, event: &EventData) {
if self.event_kind == EventKind::Modified {
self.subscriber.on_modified(event)
}
}
fn on_removed(&self, storage: &Storage, event: &EventData) {
if self.event_kind == EventKind::Removed {
self.subscriber.on_removed(storage, event)
}
}
fn is_connected(&self) -> bool {
self.subscriber.is_connected()
}
}
pub struct WithIds<S> {
sink: S,
}
impl<S> WithIds<S> {
pub fn new(sink: S) -> Self {
Self { sink }
}
}
impl<S: Sink<Entity>> Sink<Event> for WithIds<S> {
fn send(&self, event: Event) {
self.sink.send(event.id);
}
fn is_connected(&self) -> bool {
self.sink.is_connected()
}
}