87 lines
2.7 KiB
Rust
87 lines
2.7 KiB
Rust
use glam::Vec3;
|
|
|
|
use crate::components::trigger::{
|
|
TriggerEvent, TriggerEventKind, TriggerFilter, TriggerShape, TriggerState,
|
|
};
|
|
use crate::entity::EntityHandle;
|
|
use crate::world::World;
|
|
|
|
pub fn trigger_system(world: &mut World)
|
|
{
|
|
world.trigger_events.clear();
|
|
|
|
let trigger_entities: Vec<EntityHandle> = world.triggers.all();
|
|
let mut pending_events: Vec<TriggerEvent> = Vec::new();
|
|
|
|
for trigger_entity in trigger_entities
|
|
{
|
|
let trigger_pos = match world.transforms.get(trigger_entity)
|
|
{
|
|
Some(t) => t.position,
|
|
None => continue,
|
|
};
|
|
|
|
let candidate_entities: Vec<EntityHandle> = match world.triggers.get(trigger_entity)
|
|
{
|
|
Some(trigger) => match &trigger.filter
|
|
{
|
|
TriggerFilter::Player => world.player_tags.all(),
|
|
},
|
|
None => continue,
|
|
};
|
|
|
|
let activator_positions: Vec<(EntityHandle, Vec3)> = candidate_entities
|
|
.into_iter()
|
|
.filter_map(|e| world.transforms.get(e).map(|t| (e, t.position)))
|
|
.collect();
|
|
|
|
let overlapping = match world.triggers.get(trigger_entity)
|
|
{
|
|
Some(trigger) => activator_positions
|
|
.iter()
|
|
.any(|(_, pos)| match &trigger.shape
|
|
{
|
|
TriggerShape::Sphere { radius } => (trigger_pos - *pos).length() < *radius,
|
|
}),
|
|
None => continue,
|
|
};
|
|
|
|
let first_activator = activator_positions.first().map(|(e, _)| *e);
|
|
|
|
if let Some(trigger) = world.triggers.get_mut(trigger_entity)
|
|
{
|
|
match (&trigger.state, overlapping)
|
|
{
|
|
(TriggerState::Idle, true) =>
|
|
{
|
|
trigger.state = TriggerState::Inside;
|
|
if let Some(activator_entity) = first_activator
|
|
{
|
|
pending_events.push(TriggerEvent {
|
|
trigger_entity,
|
|
activator_entity,
|
|
kind: TriggerEventKind::Entered,
|
|
});
|
|
}
|
|
}
|
|
(TriggerState::Inside, false) =>
|
|
{
|
|
trigger.state = TriggerState::Idle;
|
|
if let Some(activator_entity) = first_activator
|
|
{
|
|
pending_events.push(TriggerEvent {
|
|
trigger_entity,
|
|
activator_entity,
|
|
kind: TriggerEventKind::Exited,
|
|
});
|
|
}
|
|
}
|
|
_ =>
|
|
{}
|
|
}
|
|
}
|
|
}
|
|
|
|
world.trigger_events.extend(pending_events);
|
|
}
|