use alloc::slice;
#[cfg(feature = "reflect")]
use core::any::type_name;
use core::{
fmt::{self, Debug, Formatter},
iter::Copied,
marker::PhantomData,
};
#[cfg(feature = "reflect")]
use bevy::reflect::utility::GenericTypePathCell;
use bevy::{
ecs::relationship::{RelatedSpawner, RelatedSpawnerCommands},
prelude::*,
};
#[cfg(feature = "serialize")]
use serde::{Deserialize, Serialize};
#[derive(Component, Deref)]
#[cfg_attr(
feature = "reflect",
derive(Reflect),
reflect(Clone, Component, Debug, PartialEq, type_path = false)
)]
#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
#[cfg_attr(
all(feature = "reflect", feature = "serialize"),
reflect(Serialize, Deserialize)
)]
#[relationship(relationship_target = Actions<C>)]
pub struct ActionOf<C: Component> {
#[deref]
#[relationship]
entity: Entity,
#[cfg_attr(feature = "reflect", 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> {}
#[cfg(feature = "reflect")]
impl<C: Component> TypePath for ActionOf<C> {
fn type_path() -> &'static str {
static CELL: GenericTypePathCell = GenericTypePathCell::new();
CELL.get_or_insert::<Self, _>(|| {
format!(concat!(module_path!(), "::ActionOf<{}>"), type_name::<C>())
})
}
fn short_type_path() -> &'static str {
static CELL: GenericTypePathCell = GenericTypePathCell::new();
CELL.get_or_insert::<Self, _>(|| format!("ActionOf<{}>", type_name::<C>()))
}
fn type_ident() -> Option<&'static str> {
Some("ActionOf")
}
fn module_path() -> Option<&'static str> {
Some(module_path!())
}
fn crate_name() -> Option<&'static str> {
Some(module_path!().split(':').next().unwrap())
}
}
#[derive(Component, Deref)]
#[cfg_attr(
feature = "reflect",
derive(Reflect),
reflect(Component, type_path = false)
)]
#[relationship_target(relationship = ActionOf<C>, linked_spawn)]
pub struct Actions<C: Component> {
#[deref]
#[relationship]
entities: Vec<Entity>,
#[cfg_attr(feature = "reflect", 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> {}
#[cfg(feature = "reflect")]
impl<C: Component> TypePath for Actions<C> {
fn type_path() -> &'static str {
static CELL: GenericTypePathCell = GenericTypePathCell::new();
CELL.get_or_insert::<Self, _>(|| {
format!(concat!(module_path!(), "::Actions<{}>"), type_name::<C>())
})
}
fn short_type_path() -> &'static str {
static CELL: GenericTypePathCell = GenericTypePathCell::new();
CELL.get_or_insert::<Self, _>(|| format!("Actions<{}>", type_name::<C>()))
}
fn type_ident() -> Option<&'static str> {
Some("Actions")
}
fn module_path() -> Option<&'static str> {
Some(module_path!())
}
fn crate_name() -> Option<&'static str> {
Some(module_path!().split(':').next().unwrap())
}
}
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),*])
};
}