use crate::core::geometry::{Bounds, Point};
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct HitboxId(pub u32);
#[derive(Clone, Copy, Debug)]
pub struct Hitbox {
pub id: HitboxId,
pub bounds: Bounds,
pub blocks: bool,
}
#[derive(Default)]
pub struct HitboxRegistry {
hitboxes: Vec<Hitbox>,
}
impl HitboxRegistry {
pub fn clear(&mut self) {
self.hitboxes.clear();
}
pub fn insert(&mut self, bounds: Bounds, blocks: bool) -> HitboxId {
let id = HitboxId(self.hitboxes.len() as u32);
self.hitboxes.push(Hitbox { id, bounds, blocks });
id
}
pub fn hits_at(&self, point: Point) -> impl Iterator<Item = HitboxId> + '_ {
let mut blocked = false;
self.hitboxes.iter().rev().filter_map(move |hitbox| {
if blocked || !hitbox.bounds.contains(point) {
return None;
}
blocked = hitbox.blocks;
Some(hitbox.id)
})
}
pub fn bounds(&self, id: HitboxId) -> Option<Bounds> {
self.hitboxes.get(id.0 as usize).map(|hitbox| hitbox.bounds)
}
pub fn topmost_at(&self, point: Point) -> Option<HitboxId> {
self.hits_at(point).next()
}
pub fn is_hovered(&self, id: HitboxId, point: Point) -> bool {
self.hits_at(point).any(|hit| hit == id)
}
}