use crate::{
change_detection::{MaybeLocation, Tick},
component::{Component, ComponentId, ComponentIdFor},
entity::Entity,
event::{EntityComponentsTrigger, EntityEvent, EventKey},
message::{
Message, MessageCursor, MessageId, MessageIterator, MessageIteratorWithId, Messages,
},
query::FilteredAccessSet,
relationship::RelationshipHookMode,
storage::SparseSet,
system::{Local, ReadOnlySystemParam, SystemMeta, SystemParam},
world::{unsafe_world_cell::UnsafeWorldCell, DeferredWorld, World},
};
use derive_more::derive::Into;
#[cfg(feature = "bevy_reflect")]
use bevy_reflect::Reflect;
use core::{
fmt::Debug,
iter,
marker::PhantomData,
ops::{Deref, DerefMut},
option,
};
pub type ComponentHook = for<'w> fn(DeferredWorld<'w>, HookContext);
#[derive(Clone, Copy, Debug)]
pub struct HookContext {
pub entity: Entity,
pub component_id: ComponentId,
pub caller: MaybeLocation,
pub relationship_hook_mode: RelationshipHookMode,
}
#[derive(Debug, Clone, Default)]
pub struct ComponentHooks {
pub(crate) on_add: Option<ComponentHook>,
pub(crate) on_insert: Option<ComponentHook>,
pub(crate) on_replace: Option<ComponentHook>,
pub(crate) on_remove: Option<ComponentHook>,
pub(crate) on_despawn: Option<ComponentHook>,
}
impl ComponentHooks {
pub(crate) fn update_from_component<C: Component + ?Sized>(&mut self) -> &mut Self {
if let Some(hook) = C::on_add() {
self.on_add(hook);
}
if let Some(hook) = C::on_insert() {
self.on_insert(hook);
}
if let Some(hook) = C::on_replace() {
self.on_replace(hook);
}
if let Some(hook) = C::on_remove() {
self.on_remove(hook);
}
if let Some(hook) = C::on_despawn() {
self.on_despawn(hook);
}
self
}
pub fn on_add(&mut self, hook: ComponentHook) -> &mut Self {
self.try_on_add(hook)
.expect("Component already has an on_add hook")
}
pub fn on_insert(&mut self, hook: ComponentHook) -> &mut Self {
self.try_on_insert(hook)
.expect("Component already has an on_insert hook")
}
pub fn on_replace(&mut self, hook: ComponentHook) -> &mut Self {
self.try_on_replace(hook)
.expect("Component already has an on_replace hook")
}
pub fn on_remove(&mut self, hook: ComponentHook) -> &mut Self {
self.try_on_remove(hook)
.expect("Component already has an on_remove hook")
}
pub fn on_despawn(&mut self, hook: ComponentHook) -> &mut Self {
self.try_on_despawn(hook)
.expect("Component already has an on_despawn hook")
}
pub fn try_on_add(&mut self, hook: ComponentHook) -> Option<&mut Self> {
if self.on_add.is_some() {
return None;
}
self.on_add = Some(hook);
Some(self)
}
pub fn try_on_insert(&mut self, hook: ComponentHook) -> Option<&mut Self> {
if self.on_insert.is_some() {
return None;
}
self.on_insert = Some(hook);
Some(self)
}
pub fn try_on_replace(&mut self, hook: ComponentHook) -> Option<&mut Self> {
if self.on_replace.is_some() {
return None;
}
self.on_replace = Some(hook);
Some(self)
}
pub fn try_on_remove(&mut self, hook: ComponentHook) -> Option<&mut Self> {
if self.on_remove.is_some() {
return None;
}
self.on_remove = Some(hook);
Some(self)
}
pub fn try_on_despawn(&mut self, hook: ComponentHook) -> Option<&mut Self> {
if self.on_despawn.is_some() {
return None;
}
self.on_despawn = Some(hook);
Some(self)
}
}
pub const ADD: EventKey = EventKey(ComponentId::new(0));
pub const INSERT: EventKey = EventKey(ComponentId::new(1));
pub const REPLACE: EventKey = EventKey(ComponentId::new(2));
pub const REMOVE: EventKey = EventKey(ComponentId::new(3));
pub const DESPAWN: EventKey = EventKey(ComponentId::new(4));
#[derive(Debug, Clone, EntityEvent)]
#[entity_event(trigger = EntityComponentsTrigger<'a>)]
#[cfg_attr(feature = "bevy_reflect", derive(Reflect))]
#[cfg_attr(feature = "bevy_reflect", reflect(Debug))]
#[doc(alias = "OnAdd")]
pub struct Add {
pub entity: Entity,
}
#[derive(Debug, Clone, EntityEvent)]
#[entity_event(trigger = EntityComponentsTrigger<'a>)]
#[cfg_attr(feature = "bevy_reflect", derive(Reflect))]
#[cfg_attr(feature = "bevy_reflect", reflect(Debug))]
#[doc(alias = "OnInsert")]
pub struct Insert {
pub entity: Entity,
}
#[derive(Debug, Clone, EntityEvent)]
#[entity_event(trigger = EntityComponentsTrigger<'a>)]
#[cfg_attr(feature = "bevy_reflect", derive(Reflect))]
#[cfg_attr(feature = "bevy_reflect", reflect(Debug))]
#[doc(alias = "OnReplace")]
pub struct Replace {
pub entity: Entity,
}
#[derive(Debug, Clone, EntityEvent)]
#[entity_event(trigger = EntityComponentsTrigger<'a>)]
#[cfg_attr(feature = "bevy_reflect", derive(Reflect))]
#[cfg_attr(feature = "bevy_reflect", reflect(Debug))]
#[doc(alias = "OnRemove")]
pub struct Remove {
pub entity: Entity,
}
#[derive(Debug, Clone, EntityEvent)]
#[entity_event(trigger = EntityComponentsTrigger<'a>)]
#[cfg_attr(feature = "bevy_reflect", derive(Reflect))]
#[cfg_attr(feature = "bevy_reflect", reflect(Debug))]
#[doc(alias = "OnDespawn")]
pub struct Despawn {
pub entity: Entity,
}
#[derive(Message, Debug, Clone, Into)]
#[cfg_attr(feature = "bevy_reflect", derive(Reflect))]
#[cfg_attr(feature = "bevy_reflect", reflect(Debug, Clone))]
pub struct RemovedComponentEntity(Entity);
#[derive(Debug)]
pub struct RemovedComponentReader<T>
where
T: Component,
{
reader: MessageCursor<RemovedComponentEntity>,
marker: PhantomData<T>,
}
impl<T: Component> Default for RemovedComponentReader<T> {
fn default() -> Self {
Self {
reader: Default::default(),
marker: PhantomData,
}
}
}
impl<T: Component> Deref for RemovedComponentReader<T> {
type Target = MessageCursor<RemovedComponentEntity>;
fn deref(&self) -> &Self::Target {
&self.reader
}
}
impl<T: Component> DerefMut for RemovedComponentReader<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.reader
}
}
#[derive(Default, Debug)]
pub struct RemovedComponentMessages {
event_sets: SparseSet<ComponentId, Messages<RemovedComponentEntity>>,
}
impl RemovedComponentMessages {
pub fn new() -> Self {
Self::default()
}
pub fn update(&mut self) {
for (_component_id, messages) in self.event_sets.iter_mut() {
messages.update();
}
}
pub fn iter(&self) -> impl Iterator<Item = (&ComponentId, &Messages<RemovedComponentEntity>)> {
self.event_sets.iter()
}
pub fn get(
&self,
component_id: impl Into<ComponentId>,
) -> Option<&Messages<RemovedComponentEntity>> {
self.event_sets.get(component_id.into())
}
pub fn write(&mut self, component_id: impl Into<ComponentId>, entity: Entity) {
self.event_sets
.get_or_insert_with(component_id.into(), Default::default)
.write(RemovedComponentEntity(entity));
}
}
#[derive(SystemParam)]
pub struct RemovedComponents<'w, 's, T: Component> {
component_id: ComponentIdFor<'s, T>,
reader: Local<'s, RemovedComponentReader<T>>,
message_sets: &'w RemovedComponentMessages,
}
pub type RemovedIter<'a> = iter::Map<
iter::Flatten<option::IntoIter<iter::Cloned<MessageIterator<'a, RemovedComponentEntity>>>>,
fn(RemovedComponentEntity) -> Entity,
>;
pub type RemovedIterWithId<'a> = iter::Map<
iter::Flatten<option::IntoIter<MessageIteratorWithId<'a, RemovedComponentEntity>>>,
fn(
(&RemovedComponentEntity, MessageId<RemovedComponentEntity>),
) -> (Entity, MessageId<RemovedComponentEntity>),
>;
fn map_id_messages(
(entity, id): (&RemovedComponentEntity, MessageId<RemovedComponentEntity>),
) -> (Entity, MessageId<RemovedComponentEntity>) {
(entity.clone().into(), id)
}
impl<'w, 's, T: Component> RemovedComponents<'w, 's, T> {
pub fn reader(&self) -> &MessageCursor<RemovedComponentEntity> {
&self.reader
}
pub fn reader_mut(&mut self) -> &mut MessageCursor<RemovedComponentEntity> {
&mut self.reader
}
pub fn messages(&self) -> Option<&Messages<RemovedComponentEntity>> {
self.message_sets.get(self.component_id.get())
}
pub fn reader_mut_with_messages(
&mut self,
) -> Option<(
&mut RemovedComponentReader<T>,
&Messages<RemovedComponentEntity>,
)> {
self.message_sets
.get(self.component_id.get())
.map(|messages| (&mut *self.reader, messages))
}
pub fn read(&mut self) -> RemovedIter<'_> {
self.reader_mut_with_messages()
.map(|(reader, messages)| reader.read(messages).cloned())
.into_iter()
.flatten()
.map(RemovedComponentEntity::into)
}
pub fn read_with_id(&mut self) -> RemovedIterWithId<'_> {
self.reader_mut_with_messages()
.map(|(reader, messages)| reader.read_with_id(messages))
.into_iter()
.flatten()
.map(map_id_messages)
}
pub fn len(&self) -> usize {
self.messages()
.map(|messages| self.reader.len(messages))
.unwrap_or(0)
}
pub fn is_empty(&self) -> bool {
self.messages()
.is_none_or(|messages| self.reader.is_empty(messages))
}
pub fn clear(&mut self) {
if let Some((reader, messages)) = self.reader_mut_with_messages() {
reader.clear(messages);
}
}
}
unsafe impl<'a> ReadOnlySystemParam for &'a RemovedComponentMessages {}
unsafe impl<'a> SystemParam for &'a RemovedComponentMessages {
type State = ();
type Item<'w, 's> = &'w RemovedComponentMessages;
fn init_state(_world: &mut World) -> Self::State {}
fn init_access(
_state: &Self::State,
_system_meta: &mut SystemMeta,
_component_access_set: &mut FilteredAccessSet,
_world: &mut World,
) {
}
#[inline]
unsafe fn get_param<'w, 's>(
_state: &'s mut Self::State,
_system_meta: &SystemMeta,
world: UnsafeWorldCell<'w>,
_change_tick: Tick,
) -> Self::Item<'w, 's> {
world.removed_components()
}
}