use crate::components::{transform::*, volume::*, volume_overlap::*};
use core::{
app::AppLifeCycle,
ecs::{
components::{Events, Tag},
Comp, Entity, Universe, WorldRef,
},
};
use std::collections::HashSet;
pub enum HaVolumeOverlapEvent {
Begin(Entity),
End(Entity),
}
#[derive(Debug, Default)]
pub struct HaVolumeOverlapSystemCache {
active_overlaps: HashSet<(Entity, Entity)>,
}
pub type HaVolumeOverlapSystemResources<'a> = (
WorldRef,
&'a AppLifeCycle,
&'a mut HaVolumeOverlapSystemCache,
Comp<&'a Tag>,
Comp<&'a HaTransform>,
Comp<&'a HaVolume>,
Comp<&'a mut HaVolumeOverlap>,
Comp<&'a mut Events<HaVolumeOverlapEvent>>,
);
pub fn ha_volume_overlap_system(universe: &mut Universe) {
let (world, lifecycle, mut cache, ..) =
universe.query_resources::<HaVolumeOverlapSystemResources>();
let dt = lifecycle.delta_time_seconds();
for (entity_a, (transform_a, volume_a, overlap, events)) in world
.query::<(
&HaTransform,
Option<&HaVolume>,
&mut HaVolumeOverlap,
&mut Events<HaVolumeOverlapEvent>,
)>()
.iter()
{
overlap.time += dt;
if overlap.time < overlap.delay {
continue;
}
overlap.time = 0.0;
for (entity_b, (tag, transform_b, volume_b)) in
world.query::<(&Tag, &HaTransform, &HaVolume)>().iter()
{
if entity_a != entity_b && overlap.filters.validate_tag(tag.0.as_ref()) {
let overlaps = if let Some(volume_a) = volume_a {
HaVolume::world_space_overlaps(
volume_a,
&transform_a.world_matrix(),
volume_b,
&transform_b.world_matrix(),
)
.is_some()
} else {
volume_b
.world_space_contains(
&transform_b.world_matrix(),
transform_a.get_translation(),
)
.is_some()
};
let active = cache.active_overlaps.contains(&(entity_a, entity_b));
match (overlaps, active) {
(true, false) => {
events.send(HaVolumeOverlapEvent::Begin(entity_b));
cache.active_overlaps.insert((entity_a, entity_b));
}
(false, true) => {
events.send(HaVolumeOverlapEvent::End(entity_b));
cache.active_overlaps.remove(&(entity_a, entity_b));
}
_ => {}
}
}
}
}
}