nightshade/ecs/navmesh/
components.rs1use nalgebra_glm::Vec3;
4use serde::{Deserialize, Serialize};
5
6#[derive(Debug, Clone, Serialize, Deserialize, enum2schema::Schema)]
12pub struct NavMeshAgent {
13 pub current_path: Vec<Vec3>,
15 pub current_waypoint_index: usize,
17 pub target_position: Option<Vec3>,
19 pub movement_speed: f32,
21 pub arrival_threshold: f32,
23 pub path_recalculation_threshold: f32,
25 pub agent_radius: f32,
27 pub agent_height: f32,
29 pub current_triangle: Option<usize>,
31 pub state: NavMeshAgentState,
33 pub distance_to_destination: f32,
35 pub avoidance_velocity: Vec3,
37}
38
39impl Default for NavMeshAgent {
40 fn default() -> Self {
41 Self {
42 current_path: Vec::new(),
43 current_waypoint_index: 0,
44 target_position: None,
45 movement_speed: 5.0,
46 arrival_threshold: 0.3,
47 path_recalculation_threshold: 2.0,
48 agent_radius: 0.3,
49 agent_height: 1.8,
50 current_triangle: None,
51 state: NavMeshAgentState::Idle,
52 distance_to_destination: 0.0,
53 avoidance_velocity: Vec3::zeros(),
54 }
55 }
56}
57
58impl NavMeshAgent {
59 pub fn new() -> Self {
61 Self::default()
62 }
63
64 pub fn with_speed(mut self, speed: f32) -> Self {
66 self.movement_speed = speed;
67 self
68 }
69
70 pub fn with_radius(mut self, radius: f32) -> Self {
72 self.agent_radius = radius;
73 self
74 }
75
76 pub fn with_height(mut self, height: f32) -> Self {
78 self.agent_height = height;
79 self
80 }
81
82 pub fn with_arrival_threshold(mut self, threshold: f32) -> Self {
84 self.arrival_threshold = threshold;
85 self
86 }
87
88 pub fn set_destination(&mut self, destination: Vec3) {
90 self.target_position = Some(destination);
91 self.state = NavMeshAgentState::PathPending;
92 }
93
94 pub fn clear_destination(&mut self) {
96 self.target_position = None;
97 self.current_path.clear();
98 self.current_waypoint_index = 0;
99 self.state = NavMeshAgentState::Idle;
100 }
101
102 pub fn has_path(&self) -> bool {
104 !self.current_path.is_empty()
105 }
106
107 pub fn is_moving(&self) -> bool {
109 self.state == NavMeshAgentState::Moving
110 }
111
112 pub fn current_waypoint(&self) -> Option<Vec3> {
114 self.current_path.get(self.current_waypoint_index).copied()
115 }
116
117 pub fn remaining_waypoints(&self) -> usize {
119 if self.current_waypoint_index >= self.current_path.len() {
120 0
121 } else {
122 self.current_path.len() - self.current_waypoint_index
123 }
124 }
125
126 pub fn advance_waypoint(&mut self) -> bool {
128 self.current_waypoint_index += 1;
129 if self.current_waypoint_index >= self.current_path.len() {
130 self.state = NavMeshAgentState::Arrived;
131 true
132 } else {
133 false
134 }
135 }
136}
137
138#[derive(
140 Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default, enum2schema::Schema,
141)]
142#[schema(string_enum)]
143pub enum NavMeshAgentState {
144 #[default]
146 Idle,
147 PathPending,
149 Moving,
151 Arrived,
153 NoPath,
155}