hassium_navigation/
system.rs1use crate::{
2 component::{NavAgent, NavAgentTarget, SimpleNavDriverTag},
3 resource::{NavMesh, NavMeshesRes, NavVec3},
4 Scalar,
5};
6use core::{
7 app::AppLifeCycle,
8 ecs::{Entities, Entity, Join, Read, ReadExpect, ReadStorage, System, WriteStorage},
9};
10use std::collections::HashMap;
11
12#[derive(Default)]
14pub struct NavAgentMaintainSystem(HashMap<Entity, Vec<NavVec3>>);
15
16impl NavAgentMaintainSystem {
17 pub fn with_cache_capacity(capacity: usize) -> Self {
18 Self(HashMap::with_capacity(capacity))
19 }
20}
21
22impl<'s> System<'s> for NavAgentMaintainSystem {
23 type SystemData = (
24 Entities<'s>,
25 Read<'s, NavMeshesRes>,
26 WriteStorage<'s, NavAgent>,
27 );
28
29 fn run(&mut self, (entities, meshes_res, mut agents): Self::SystemData) {
30 self.0.clear();
31 for (entity, agent) in (&entities, &agents).join() {
32 if agent.dirty_path {
33 if let Some(destination) = &agent.destination {
34 if let Some(mesh) = meshes_res.0.get(&destination.mesh) {
35 match destination.target {
36 NavAgentTarget::Point(point) => {
37 if let Some(path) = mesh.find_path(
38 agent.position,
39 point,
40 destination.query,
41 destination.mode,
42 ) {
43 self.0.insert(entity, path);
44 }
45 }
46 NavAgentTarget::Entity(entity) => {
47 if let Some(other) = agents.get(entity) {
48 if let Some(path) = mesh.find_path(
49 agent.position,
50 other.position,
51 destination.query,
52 destination.mode,
53 ) {
54 self.0.insert(entity, path);
55 }
56 }
57 }
58 }
59 }
60 }
61 }
62 }
63 for (entity, path) in self.0.drain() {
64 if let Some(agent) = agents.get_mut(entity) {
65 agent.set_path(path);
66 }
67 }
68 }
69}
70
71pub struct SimpleNavDriverSystem;
74
75impl SimpleNavDriverSystem {
76 pub fn run_impl<'s>(
78 delta_time: Scalar,
79 (mut agents, drivers): (
80 WriteStorage<'s, NavAgent>,
81 ReadStorage<'s, SimpleNavDriverTag>,
82 ),
83 ) {
84 if delta_time <= 0.0 {
85 return;
86 }
87 for (agent, _) in (&mut agents, &drivers).join() {
88 if let Some(path) = agent.path() {
89 if let Some((target, _)) = NavMesh::path_target_point(
90 path,
91 agent.position,
92 agent.speed.max(agent.min_target_distance.max(0.0)) * delta_time,
93 ) {
94 let diff = target - agent.position;
95 let dir = diff.normalize();
96 agent.position = agent.position
97 + dir * (agent.speed.max(0.0) * delta_time).min(diff.magnitude());
98 agent.direction = diff.normalize();
99 }
100 }
101 }
102 }
103}
104
105impl<'s> System<'s> for SimpleNavDriverSystem {
106 type SystemData = (
107 ReadExpect<'s, AppLifeCycle>,
108 WriteStorage<'s, NavAgent>,
109 ReadStorage<'s, SimpleNavDriverTag>,
110 );
111
112 fn run(&mut self, (lifecycle, agents, drivers): Self::SystemData) {
113 let delta_time = lifecycle.delta_time_seconds();
114 Self::run_impl(delta_time, (agents, drivers));
115 }
116}