bsp_pathfinding/
navigation_context.rs1use crate::{
2 astar::{astar, Path, SearchInfo},
3 BSPNode, BSPTree, NodeIndex, NodePayload, PortalIter,
4};
5use glam::Vec2;
6use rand::Rng;
7
8use crate::{Face, Portals};
9
10#[derive(Default)]
12#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
13pub struct NavigationContext {
14 tree: Option<BSPTree>,
15 portals: Portals,
16}
17
18impl NavigationContext {
19 pub fn new(faces: impl IntoIterator<Item = Face>) -> Self {
21 let tree = BSPTree::new(faces.into_iter());
22 let mut portals = Portals::new();
23 if let Some(tree) = tree.as_ref() {
24 portals.generate(&tree);
25 }
26
27 Self { tree, portals }
28 }
29
30 pub fn new_shuffle(faces: impl IntoIterator<Item = Face>, rng: &mut impl Rng) -> Self {
33 let tree = BSPTree::new_shuffle(faces.into_iter(), rng);
34 let mut portals = Portals::new();
35 if let Some(tree) = tree.as_ref() {
36 portals.generate(&tree);
37 }
38
39 Self { tree, portals }
40 }
41 pub fn node(&self, index: NodeIndex) -> Option<&BSPNode> {
42 self.tree.as_ref()?.node(index)
43 }
44
45 pub fn locate(&self, point: Vec2) -> Option<NodePayload> {
48 match &self.tree {
49 Some(tree) => Some(tree.locate(point)),
50 None => None,
51 }
52 }
53
54 pub fn tree(&self) -> Option<&BSPTree> {
56 self.tree.as_ref()
57 }
58
59 pub fn portals(&self) -> &Portals {
61 &self.portals
62 }
63
64 pub fn get(&self, index: NodeIndex) -> PortalIter {
66 self.portals.get(index)
67 }
68
69 pub fn find_path(
73 &self,
74 start: Vec2,
75 end: Vec2,
76 heuristic: impl Fn(Vec2, Vec2) -> f32,
77 info: SearchInfo,
78 ) -> Option<Path> {
79 let mut path = None;
80 match &self.tree {
81 Some(tree) => {
82 astar(&tree, &self.portals, start, end, heuristic, info, &mut path);
83 path
84 }
85 None => Some(Path::euclidian(start, end)),
86 }
87 }
88
89 pub fn find_path_inc<'a>(
95 &self,
96 start: Vec2,
97 end: Vec2,
98 heuristic: impl Fn(Vec2, Vec2) -> f32,
99 info: SearchInfo,
100 path: &'a mut Option<Path>,
101 ) -> Option<&'a mut Path> {
102 match &self.tree {
103 Some(tree) => astar(&tree, &self.portals, start, end, heuristic, info, path),
104 None => {
105 *path = Some(Path::euclidian(start, end));
106 path.as_mut()
107 }
108 }
109 }
110}