use alloc::slice;
use core::{
fmt::{self, Debug, Formatter},
iter::Copied,
marker::PhantomData,
};
use bevy::{
ecs::relationship::{RelatedSpawner, RelatedSpawnerCommands},
prelude::*,
};
#[cfg(feature = "serialize")]
use serde::{Deserialize, Serialize};
#[derive(Component, Deref, Reflect)]
#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serialize", reflect(Serialize, Deserialize))]
#[relationship(relationship_target = Actions<C>)]
pub struct ActionOf<C: Component> {
#[deref]
#[relationship]
entity: Entity,
#[reflect(ignore)]
marker: PhantomData<C>,
}
impl<C: Component> ActionOf<C> {
#[must_use]
pub const fn new(entity: Entity) -> Self {
Self {
entity,
marker: PhantomData,
}
}
}
impl<C: Component> Debug for ActionOf<C> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
f.debug_struct("ActionOf")
.field("entity", &self.entity)
.finish()
}
}
impl<C: Component> Clone for ActionOf<C> {
fn clone(&self) -> Self {
Self {
entity: self.entity,
marker: PhantomData,
}
}
}
impl<C: Component> PartialEq for ActionOf<C> {
fn eq(&self, other: &Self) -> bool {
self.entity == other.entity
}
}
impl<C: Component> Eq for ActionOf<C> {}
#[derive(Component, Deref, Reflect)]
#[relationship_target(relationship = ActionOf<C>, linked_spawn)]
pub struct Actions<C: Component> {
#[deref]
#[relationship]
entities: Vec<Entity>,
#[reflect(ignore)]
marker: PhantomData<C>,
}
impl<'a, C: Component> IntoIterator for &'a Actions<C> {
type Item = Entity;
type IntoIter = Copied<slice::Iter<'a, Entity>>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<C: Component> Default for Actions<C> {
fn default() -> Self {
Self {
entities: Default::default(),
marker: PhantomData,
}
}
}
impl<C: Component> Debug for Actions<C> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
f.debug_struct("Actions")
.field("entities", &self.entities)
.finish()
}
}
impl<C: Component> Clone for Actions<C> {
fn clone(&self) -> Self {
Self {
entities: self.entities.clone(),
marker: PhantomData,
}
}
}
impl<C: Component> PartialEq for Actions<C> {
fn eq(&self, other: &Self) -> bool {
self.entities == other.entities
}
}
impl<C: Component> Eq for Actions<C> {}
pub type ActionSpawner<'w, C> = RelatedSpawner<'w, ActionOf<C>>;
pub type ActionSpawnerCommands<'w, C> = RelatedSpawnerCommands<'w, ActionOf<C>>;
#[macro_export]
macro_rules! actions {
($context:ty [$($action:expr),*$(,)?]) => {
::bevy::prelude::related!($crate::prelude::Actions<$context>[$($action),*])
};
}