use crate::resources::{NavMeshID, NavPathMode, NavQuery, NavVec3};
use core::{
ecs::Entity,
id::ID,
prefab::{Prefab, PrefabComponent},
Scalar,
};
use serde::{Deserialize, Serialize};
pub type NavAgentId = ID<NavAgent>;
#[derive(Debug, Default, Copy, Clone, Serialize, Deserialize)]
pub struct SimpleNavDriverTag;
impl Prefab for SimpleNavDriverTag {}
impl PrefabComponent for SimpleNavDriverTag {}
#[derive(Debug, Clone, Copy)]
pub enum NavAgentTarget {
Point(NavVec3),
Entity(Entity),
}
impl NavAgentTarget {
pub fn is_point(&self) -> bool {
matches!(self, NavAgentTarget::Point(_))
}
pub fn is_entity(&self) -> bool {
matches!(self, NavAgentTarget::Entity(_))
}
}
#[derive(Debug, Clone)]
pub struct NavAgentDestination {
pub target: NavAgentTarget,
pub query: NavQuery,
pub mode: NavPathMode,
pub mesh: NavMeshID,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NavAgent {
id: NavAgentId,
pub position: NavVec3,
pub direction: NavVec3,
pub speed: Scalar,
pub radius: Scalar,
pub min_target_distance: Scalar,
#[serde(skip)]
pub(crate) destination: Option<NavAgentDestination>,
#[serde(skip)]
pub(crate) path: Option<Vec<NavVec3>>,
#[serde(skip)]
pub(crate) dirty_path: bool,
}
impl Default for NavAgent {
fn default() -> Self {
Self::new(Default::default())
}
}
impl NavAgent {
pub fn new(position: NavVec3) -> Self {
Self::new_with_direction(position, Default::default())
}
pub fn new_with_direction(position: NavVec3, direction: NavVec3) -> Self {
Self {
id: Default::default(),
position,
direction: direction.normalize(),
speed: 10.0,
radius: 1.0,
min_target_distance: 1.0,
destination: None,
path: None,
dirty_path: false,
}
}
pub fn id(&self) -> NavAgentId {
self.id
}
pub fn target(&self) -> Option<NavAgentTarget> {
self.destination
.as_ref()
.map(|destination| destination.target)
}
pub fn destination(&self) -> Option<&NavAgentDestination> {
self.destination.as_ref()
}
pub fn set_destination(
&mut self,
target: NavAgentTarget,
query: NavQuery,
mode: NavPathMode,
mesh: NavMeshID,
) {
self.destination = Some(NavAgentDestination {
target,
query,
mode,
mesh,
});
self.dirty_path = true;
}
pub fn clear_path(&mut self) {
self.destination = None;
self.dirty_path = false;
self.path = None;
}
pub fn recalculate_path(&mut self) {
self.dirty_path = true;
}
pub fn path(&self) -> Option<&[NavVec3]> {
if let Some(path) = &self.path {
Some(path)
} else {
None
}
}
pub fn set_path(&mut self, path: Vec<NavVec3>) {
self.path = Some(path);
self.dirty_path = false;
}
}
impl Prefab for NavAgent {}
impl PrefabComponent for NavAgent {}