oxygengine_navigation/
components.rs

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