oxygengine_navigation/
systems.rs

1use crate::{
2    components::{NavAgent, NavAgentTarget, SimpleNavDriverTag},
3    resources::{nav_meshes::NavMeshes, NavMesh},
4};
5use core::{
6    app::AppLifeCycle,
7    ecs::{Comp, Universe, WorldRef},
8};
9
10pub type NavAgentMaintainSystemResources<'a> = (WorldRef, &'a NavMeshes, Comp<&'a mut NavAgent>);
11
12pub fn nav_agent_maintain_system(universe: &mut Universe) {
13    let (world, meshes, ..) = universe.query_resources::<NavAgentMaintainSystemResources>();
14
15    for (entity, agent) in world.query::<&mut NavAgent>().iter() {
16        if agent.dirty_path {
17            if let Some(destination) = &agent.destination {
18                if let Some(mesh) = meshes.0.get(&destination.mesh) {
19                    match destination.target {
20                        NavAgentTarget::Point(point) => {
21                            if let Some(path) = mesh.find_path(
22                                agent.position,
23                                point,
24                                destination.query,
25                                destination.mode,
26                            ) {
27                                agent.set_path(path);
28                            }
29                        }
30                        NavAgentTarget::Entity(other) => {
31                            if entity != other {
32                                if let Ok(other) =
33                                    unsafe { world.get_unchecked::<&NavAgent>(other) }
34                                {
35                                    if let Some(path) = mesh.find_path(
36                                        agent.position,
37                                        other.position,
38                                        destination.query,
39                                        destination.mode,
40                                    ) {
41                                        agent.set_path(path);
42                                    }
43                                }
44                            }
45                        }
46                    }
47                }
48            }
49        }
50    }
51}
52
53pub type SimpleNavDriverSystemResources<'a> = (
54    WorldRef,
55    &'a AppLifeCycle,
56    Comp<&'a mut NavAgent>,
57    Comp<&'a SimpleNavDriverTag>,
58);
59
60pub fn simple_nav_driver_system(universe: &mut Universe) {
61    let (world, lifecycle, ..) = universe.query_resources::<SimpleNavDriverSystemResources>();
62
63    let delta_time = lifecycle.delta_time_seconds();
64    if delta_time <= 0.0 {
65        return;
66    }
67    for (_, agent) in world
68        .query::<&mut NavAgent>()
69        .with::<&SimpleNavDriverTag>()
70        .iter()
71    {
72        if let Some(path) = agent.path() {
73            if let Some((target, _)) = NavMesh::path_target_point(
74                path,
75                agent.position,
76                agent.speed.max(agent.min_target_distance.max(0.0)) * delta_time,
77            ) {
78                let diff = target - agent.position;
79                let dir = diff.normalize();
80                agent.position = agent.position
81                    + dir * (agent.speed.max(0.0) * delta_time).min(diff.magnitude());
82                agent.direction = diff.normalize();
83            }
84        }
85    }
86}