use crate::prelude::*;
use bevy::ecs::system::SystemParam;
use bevy::prelude::*;
#[derive(Resource)]
pub(crate) struct DespawnAccessTracker
{
currently_reacting: bool,
reaction_source: Entity,
reactor_handle: Option<ReactorHandle>,
prepared: Vec<(SystemCommand, Entity, ReactorHandle)>,
}
impl DespawnAccessTracker
{
pub(crate) fn prepare(&mut self, reactor: SystemCommand, source: Entity, handle: ReactorHandle)
{
self.prepared.push((reactor, source, handle));
}
pub(crate) fn start(&mut self, reactor: SystemCommand)
{
let Some(pos) = self.prepared.iter().position(|(s, _, _)| *s == reactor) else {
tracing::error!("prepared despawn entity reaction is missing {:?}", reactor);
debug_assert!(false);
return;
};
let (_, source, handle) = self.prepared.swap_remove(pos);
self.currently_reacting = true;
self.reaction_source = source;
self.reactor_handle = Some(handle);
}
pub(crate) fn end(&mut self)
{
self.currently_reacting = false;
self.reactor_handle = None;
}
fn is_reacting(&self) -> bool
{
self.currently_reacting
}
fn source(&self) -> Entity
{
self.reaction_source
}
}
impl Default for DespawnAccessTracker
{
fn default() -> Self
{
Self{
currently_reacting: false,
reaction_source: Entity::from_raw(0u32),
reactor_handle: None,
prepared: Vec::default(),
}
}
}
#[derive(SystemParam)]
pub struct DespawnEvent<'w>
{
tracker: Res<'w, DespawnAccessTracker>,
}
impl<'w> DespawnEvent<'w>
{
pub fn entity(&self) -> Entity
{
self.get().expect("failed reading despawn event, there is no entity")
}
pub fn get(&self) -> Option<Entity>
{
if !self.tracker.is_reacting() { return None; }
Some(self.tracker.source())
}
pub fn is_empty(&self) -> bool
{
self.get().is_none()
}
}