Skip to main content

hassium_navigation/
component.rs

1use crate::{
2    resource::{NavMeshID, NavPathMode, NavQuery, NavVec3},
3    Scalar,
4};
5use core::{
6    ecs::{Component, Entity, NullStorage, VecStorage},
7    id::ID,
8};
9
10/// Nav agent identifier.
11pub type NavAgentID = ID<NavAgent>;
12
13/// Simple nav driver component tag to mark entity to use simple movement on nav mesh.
14#[derive(Debug, Default, Copy, Clone)]
15pub struct SimpleNavDriverTag;
16
17impl Component for SimpleNavDriverTag {
18    type Storage = NullStorage<Self>;
19}
20
21/// Nav agent target.
22#[derive(Debug, Clone, Copy)]
23pub enum NavAgentTarget {
24    /// Point in world space.
25    Point(NavVec3),
26    /// Entity to follow.
27    Entity(Entity),
28}
29
30impl NavAgentTarget {
31    pub fn is_point(&self) -> bool {
32        match self {
33            NavAgentTarget::Point(_) => true,
34            _ => false,
35        }
36    }
37
38    pub fn is_entity(&self) -> bool {
39        match self {
40            NavAgentTarget::Entity(_) => true,
41            _ => false,
42        }
43    }
44}
45
46/// Nav agent destination descriptor.
47#[derive(Debug, Clone)]
48pub struct NavAgentDestination {
49    /// Target.
50    pub target: NavAgentTarget,
51    /// Query quality.
52    pub query: NavQuery,
53    /// path finding quality.
54    pub mode: NavPathMode,
55    /// Nav mesh identifier that agent is moving on.
56    pub mesh: NavMeshID,
57}
58
59/// Nav agent component.
60#[derive(Debug, Clone)]
61pub struct NavAgent {
62    id: NavAgentID,
63    /// Current agent position in world space.
64    pub position: NavVec3,
65    /// Current agent normalized direction.
66    pub direction: NavVec3,
67    /// Current speed (units per second).
68    pub speed: Scalar,
69    /// Agent sphere radius (used in obstacle and agent avoidance).
70    pub radius: Scalar,
71    /// Mnimal distance to target (affects direction, tells how far look for point to go to in an
72    /// instant).
73    pub min_target_distance: Scalar,
74    pub(crate) destination: Option<NavAgentDestination>,
75    pub(crate) path: Option<Vec<NavVec3>>,
76    pub(crate) dirty_path: bool,
77}
78
79impl Component for NavAgent {
80    type Storage = VecStorage<Self>;
81}
82
83impl Default for NavAgent {
84    fn default() -> Self {
85        Self::new(Default::default())
86    }
87}
88
89impl NavAgent {
90    pub fn new(position: NavVec3) -> Self {
91        Self::new_with_direction(position, Default::default())
92    }
93
94    pub fn new_with_direction(position: NavVec3, direction: NavVec3) -> Self {
95        Self {
96            id: Default::default(),
97            position,
98            direction: direction.normalize(),
99            speed: 10.0,
100            radius: 1.0,
101            min_target_distance: 1.0,
102            destination: None,
103            path: None,
104            dirty_path: false,
105        }
106    }
107
108    pub fn id(&self) -> NavAgentID {
109        self.id
110    }
111
112    pub fn target(&self) -> Option<NavAgentTarget> {
113        if let Some(destination) = &self.destination {
114            Some(destination.target)
115        } else {
116            None
117        }
118    }
119
120    pub fn destination(&self) -> Option<&NavAgentDestination> {
121        if let Some(destination) = &self.destination {
122            Some(destination)
123        } else {
124            None
125        }
126    }
127
128    /// Sets destination to go to.
129    ///
130    /// # Arguments
131    /// * `target` - target to go to.
132    /// * `query` - query quality.
133    /// * `mode` - path finding quality.
134    /// * `mesh` - nav mesh to move on.
135    pub fn set_destination(
136        &mut self,
137        target: NavAgentTarget,
138        query: NavQuery,
139        mode: NavPathMode,
140        mesh: NavMeshID,
141    ) {
142        self.destination = Some(NavAgentDestination {
143            target,
144            query,
145            mode,
146            mesh,
147        });
148        self.dirty_path = true;
149    }
150
151    pub fn clear_path(&mut self) {
152        self.destination = None;
153        self.dirty_path = false;
154        self.path = None;
155    }
156
157    pub fn recalculate_path(&mut self) {
158        self.dirty_path = true;
159    }
160
161    pub fn path(&self) -> Option<&[NavVec3]> {
162        if let Some(path) = &self.path {
163            Some(path)
164        } else {
165            None
166        }
167    }
168
169    pub fn set_path(&mut self, path: Vec<NavVec3>) {
170        self.path = Some(path);
171        self.dirty_path = false;
172    }
173}