bevy_tnua/control_helpers/
blip_reuse_avoidance.rs1use bevy::platform::collections::HashMap;
2use bevy::prelude::*;
3use bevy_tnua_physics_integration_layer::obstacle_radar::TnuaObstacleRadar;
4
5use crate::TnuaScheme;
6use crate::controller::TnuaActionFlowStatus;
7use crate::prelude::TnuaController;
8
9#[derive(Component)]
15pub struct TnuaBlipReuseAvoidance<S: TnuaScheme> {
16 current_entity: Option<Entity>,
17 entities_to_avoid: HashMap<Entity, S::ActionDiscriminant>,
18}
19
20impl<S: TnuaScheme> Default for TnuaBlipReuseAvoidance<S> {
21 fn default() -> Self {
22 Self {
23 current_entity: None,
24 entities_to_avoid: Default::default(),
25 }
26 }
27}
28
29pub trait TnuaHasTargetEntity: TnuaScheme {
31 fn target_entity(action_state: &Self::ActionState) -> Option<Entity>;
37}
38
39impl<S> TnuaBlipReuseAvoidance<S>
40where
41 S: TnuaScheme + TnuaHasTargetEntity,
42{
43 pub fn update(&mut self, controller: &TnuaController<S>, radar: &TnuaObstacleRadar) {
45 let current_entity = controller
46 .current_action
47 .as_ref()
48 .and_then(S::target_entity);
49
50 if current_entity != self.current_entity
51 && let Some(old_entity) = self.current_entity.as_ref()
52 && let TnuaActionFlowStatus::ActionEnded(action_discriminant)
53 | TnuaActionFlowStatus::Cancelled {
54 old: action_discriminant,
55 new: _,
56 } = controller.action_flow_status()
57 {
58 self.entities_to_avoid
59 .insert(*old_entity, *action_discriminant);
60 }
61
62 self.entities_to_avoid
63 .retain(|entity, _| radar.has_blip(*entity));
64
65 self.current_entity = current_entity;
66 }
67
68 pub fn should_avoid(&self, entity: Entity) -> bool {
71 self.entities_to_avoid.contains_key(&entity)
72 }
73}