mirror of https://codeberg.org/topola/topola.git
feat(router/navcord): Make it possible to visit leap navnodes
Closes https://codeberg.org/topola/topola/issues/121
This commit is contained in:
parent
a27b263288
commit
aef5c6471e
|
|
@ -18,7 +18,7 @@ use crate::{
|
||||||
use super::{
|
use super::{
|
||||||
draw::Draw,
|
draw::Draw,
|
||||||
navcorder::{Navcorder, NavcorderException},
|
navcorder::{Navcorder, NavcorderException},
|
||||||
navmesh::{NavigableNodeIndex, Navmesh, NavnodeIndex},
|
navmesh::{NavigableNodeIndex, Navmesh, NavnodeIndex, NavnodeWeight},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The `Navcord` is a data structure that holds the movable non-borrowing data
|
/// The `Navcord` is a data structure that holds the movable non-borrowing data
|
||||||
|
|
@ -106,17 +106,20 @@ impl Navcord {
|
||||||
navmesh: &Navmesh,
|
navmesh: &Navmesh,
|
||||||
to: NavnodeIndex,
|
to: NavnodeIndex,
|
||||||
) -> Result<(), NavcorderException> {
|
) -> Result<(), NavcorderException> {
|
||||||
|
let to_node_weight = navmesh.node_weight(to).unwrap();
|
||||||
|
|
||||||
if to == navmesh.destination_navnode() {
|
if to == navmesh.destination_navnode() {
|
||||||
let to_node_weight = navmesh.node_weight(to).unwrap();
|
|
||||||
let NavigableNodeIndex::FixedDot(to_dot) = to_node_weight.node() else {
|
let NavigableNodeIndex::FixedDot(to_dot) = to_node_weight.node() else {
|
||||||
unreachable!();
|
unreachable!();
|
||||||
};
|
};
|
||||||
|
|
||||||
self.final_termseg = Some(layout.finish(navmesh, self, to_dot).unwrap());
|
self.final_termseg = Some(layout.finish(navmesh, self, to_dot)?);
|
||||||
|
|
||||||
// NOTE: We don't update the head here because there is currently
|
// NOTE: We don't update the head here because there is currently
|
||||||
// no head variant that consists only of a seg, and I'm not sure if
|
// no head variant that consists only of a seg, and I'm not sure if
|
||||||
// there should be one.
|
// there should be one.
|
||||||
|
} else if matches!(to_node_weight, NavnodeWeight::Leap(..)) {
|
||||||
|
// Nothing to do beyond pushing the navnode onto the path.
|
||||||
} else {
|
} else {
|
||||||
self.head = self.wrap(layout, navmesh, self.head, to)?.into();
|
self.head = self.wrap(layout, navmesh, self.head, to)?.into();
|
||||||
}
|
}
|
||||||
|
|
@ -134,10 +137,15 @@ impl Navcord {
|
||||||
pub fn step_back<R: AccessRules>(
|
pub fn step_back<R: AccessRules>(
|
||||||
&mut self,
|
&mut self,
|
||||||
layout: &mut Layout<R>,
|
layout: &mut Layout<R>,
|
||||||
|
navmesh: &Navmesh,
|
||||||
) -> Result<(), NavcorderException> {
|
) -> Result<(), NavcorderException> {
|
||||||
|
let last_node_weight = navmesh.node_weight(*self.path.last().unwrap());
|
||||||
|
|
||||||
if let Some(final_termseg) = self.final_termseg {
|
if let Some(final_termseg) = self.final_termseg {
|
||||||
layout.remove_termseg(&mut self.recorder, final_termseg);
|
layout.remove_termseg(&mut self.recorder, final_termseg);
|
||||||
self.final_termseg = None;
|
self.final_termseg = None;
|
||||||
|
} else if matches!(last_node_weight, Some(NavnodeWeight::Leap(..))) {
|
||||||
|
// Nothing to do beyond popping the navnode from the path.
|
||||||
} else {
|
} else {
|
||||||
if let Head::Cane(head) = self.head {
|
if let Head::Cane(head) = self.head {
|
||||||
self.head = layout.undo_cane(&mut self.recorder, head).unwrap();
|
self.head = layout.undo_cane(&mut self.recorder, head).unwrap();
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ pub trait Navcorder {
|
||||||
path: &[NavnodeIndex],
|
path: &[NavnodeIndex],
|
||||||
) -> Result<(), NavcorderException>;
|
) -> Result<(), NavcorderException>;
|
||||||
|
|
||||||
fn undo_path(&mut self, navcord: &mut Navcord, step_count: usize);
|
fn undo_path(&mut self, navmesh: &Navmesh, navcord: &mut Navcord, step_count: usize);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R: AccessRules> Navcorder for Layout<R> {
|
impl<R: AccessRules> Navcorder for Layout<R> {
|
||||||
|
|
@ -93,7 +93,7 @@ impl<R: AccessRules> Navcorder for Layout<R> {
|
||||||
.count();
|
.count();
|
||||||
|
|
||||||
let length = navcord.path.len();
|
let length = navcord.path.len();
|
||||||
self.undo_path(navcord, length - prefix_length);
|
self.undo_path(navmesh, navcord, length - prefix_length);
|
||||||
self.path(navmesh, navcord, &path[prefix_length..])
|
self.path(navmesh, navcord, &path[prefix_length..])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -106,7 +106,7 @@ impl<R: AccessRules> Navcorder for Layout<R> {
|
||||||
) -> Result<(), NavcorderException> {
|
) -> Result<(), NavcorderException> {
|
||||||
for (i, vertex) in path.iter().enumerate() {
|
for (i, vertex) in path.iter().enumerate() {
|
||||||
if let Err(err) = navcord.step_to(self, navmesh, *vertex) {
|
if let Err(err) = navcord.step_to(self, navmesh, *vertex) {
|
||||||
self.undo_path(navcord, i);
|
self.undo_path(navmesh, navcord, i);
|
||||||
return Err(err);
|
return Err(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -115,9 +115,9 @@ impl<R: AccessRules> Navcorder for Layout<R> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[debug_ensures(navcord.path.len() == old(navcord.path.len() - step_count))]
|
#[debug_ensures(navcord.path.len() == old(navcord.path.len() - step_count))]
|
||||||
fn undo_path(&mut self, navcord: &mut Navcord, step_count: usize) {
|
fn undo_path(&mut self, navmesh: &Navmesh, navcord: &mut Navcord, step_count: usize) {
|
||||||
for _ in 0..step_count {
|
for _ in 0..step_count {
|
||||||
let _ = navcord.step_back(self);
|
let _ = navcord.step_back(self, navmesh);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -90,7 +90,7 @@ impl<R: AccessRules> Step<Router<'_, R>, BandTermsegIndex> for RouteStepper {
|
||||||
// NOTE(fogti): The 1 instead 0 is because the first element in the path
|
// NOTE(fogti): The 1 instead 0 is because the first element in the path
|
||||||
// is the source navnode. See also: `NavcordStepper::new`.
|
// is the source navnode. See also: `NavcordStepper::new`.
|
||||||
for _ in 1..self.navcord.path.len() {
|
for _ in 1..self.navcord.path.len() {
|
||||||
self.navcord.step_back(layout);
|
self.navcord.step_back(layout, &self.astar.graph);
|
||||||
}
|
}
|
||||||
Err(e)
|
Err(e)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -136,8 +136,8 @@ impl<R: AccessRules> AstarStrategy<Navmesh, f64, BandTermsegIndex> for RouterAst
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_probe(&mut self, _navmesh: &Navmesh) {
|
fn remove_probe(&mut self, navmesh: &Navmesh) {
|
||||||
self.navcord.step_back(self.layout);
|
self.navcord.step_back(self.layout, navmesh);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn estimate_cost(&mut self, navmesh: &Navmesh, vertex: NavnodeIndex) -> f64 {
|
fn estimate_cost(&mut self, navmesh: &Navmesh, vertex: NavnodeIndex) -> f64 {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue