trigger system
This commit is contained in:
82
src/systems/trigger.rs
Normal file
82
src/systems/trigger.rs
Normal file
@@ -0,0 +1,82 @@
|
||||
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);
|
||||
}
|
||||
Reference in New Issue
Block a user