feat(autorouter): use recorded edit applying for undo/redo

This commit is contained in:
Mikolaj Wielgus 2024-12-03 08:35:11 +01:00
parent d17a34c0f6
commit c2daf9fbfe
3 changed files with 63 additions and 41 deletions

View File

@ -10,7 +10,7 @@ use thiserror::Error;
use crate::{ use crate::{
board::mesadata::AccessMesadata, board::mesadata::AccessMesadata,
drawing::graph::PrimitiveIndex, drawing::graph::PrimitiveIndex,
geometry::primitive::PrimitiveShape, geometry::{edit::ApplyGeometryEdit, primitive::PrimitiveShape},
router::{navcord::NavcordStepper, navmesh::Navmesh}, router::{navcord::NavcordStepper, navmesh::Navmesh},
stepper::Step, stepper::Step,
}; };
@ -172,20 +172,10 @@ impl<M: AccessMesadata> Invoker<M> {
#[debug_requires(self.ongoing_command.is_none())] #[debug_requires(self.ongoing_command.is_none())]
/// Undo last command /// Undo last command
pub fn undo(&mut self) -> Result<(), InvokerError> { pub fn undo(&mut self) -> Result<(), InvokerError> {
let command = self.history.last_done()?.command(); let last_done = self.history.last_done()?;
match command { if let Some(edit) = last_done.edit() {
Command::Autoroute(ref selection, ..) => { self.autorouter.board.apply(edit.reverse());
self.autorouter.undo_autoroute(selection)?;
}
Command::PlaceVia(weight) => {
self.autorouter.undo_place_via(*weight);
}
Command::RemoveBands(ref selection) => {
self.autorouter.undo_remove_bands(selection);
}
Command::CompareDetours(..) => {}
Command::MeasureLength(..) => {}
} }
Ok(self.history.undo()?) Ok(self.history.undo()?)
@ -194,19 +184,13 @@ impl<M: AccessMesadata> Invoker<M> {
//#[debug_requires(self.ongoing_command.is_none())] //#[debug_requires(self.ongoing_command.is_none())]
/// Redo last command /// Redo last command
pub fn redo(&mut self) -> Result<(), InvokerError> { pub fn redo(&mut self) -> Result<(), InvokerError> {
let command = self.history.last_undone()?.command().clone(); let last_undone = self.history.last_undone()?;
let mut execute = self.execute_stepper(command)?;
loop { if let Some(edit) = last_undone.edit() {
let status = match execute.step(self) { self.autorouter.board.apply(edit.clone());
Ok(status) => status,
Err(err) => return Err(err),
};
if let ControlFlow::Break(..) = status {
return Ok(self.history.redo()?);
}
} }
Ok(self.history.redo()?)
} }
#[debug_requires(self.ongoing_command.is_none())] #[debug_requires(self.ongoing_command.is_none())]

View File

@ -62,4 +62,34 @@ impl<
primitive_weight_marker: PhantomData, primitive_weight_marker: PhantomData,
} }
} }
pub fn reverse(&self) -> Self {
Self {
dots: self
.dots
.clone()
.into_iter()
.map(|(k, v)| (k, (v.1, v.0)))
.collect(),
segs: self
.segs
.clone()
.into_iter()
.map(|(k, v)| (k, (v.1, v.0)))
.collect(),
bends: self
.bends
.clone()
.into_iter()
.map(|(k, v)| (k, (v.1, v.0)))
.collect(),
compounds: self
.compounds
.clone()
.into_iter()
.map(|(k, v)| (k, (v.1, v.0)))
.collect(),
primitive_weight_marker: PhantomData,
}
}
} }

View File

@ -396,44 +396,52 @@ impl<
for RecordingGeometryWithRtree<PW, DW, SW, BW, CW, PI, DI, SI, BI> for RecordingGeometryWithRtree<PW, DW, SW, BW, CW, PI, DI, SI, BI>
{ {
fn apply(&mut self, edit: GeometryEdit<PW, DW, SW, BW, CW, PI, DI, SI, BI>) { fn apply(&mut self, edit: GeometryEdit<PW, DW, SW, BW, CW, PI, DI, SI, BI>) {
for (compound, ..) in &edit.compounds { for (compound, (maybe_old_data, ..)) in &edit.compounds {
self.geometry_with_rtree.remove_compound(*compound); if maybe_old_data.is_some() {
self.geometry_with_rtree.remove_compound(*compound);
}
} }
for (bend, ..) in &edit.bends { for (bend, (maybe_old_data, ..)) in &edit.bends {
self.geometry_with_rtree.remove_bend(*bend); if maybe_old_data.is_some() {
self.geometry_with_rtree.remove_bend(*bend);
}
} }
for (seg, ..) in &edit.segs { for (seg, (maybe_old_data, ..)) in &edit.segs {
self.geometry_with_rtree.remove_seg(*seg); if maybe_old_data.is_some() {
self.geometry_with_rtree.remove_seg(*seg);
}
} }
for (dot, ..) in &edit.dots { for (dot, (maybe_old_data, ..)) in &edit.dots {
self.geometry_with_rtree.remove_dot(*dot); if maybe_old_data.is_some() {
self.geometry_with_rtree.remove_dot(*dot);
}
} }
for (dot, (.., maybe_weight)) in &edit.dots { for (dot, (.., maybe_new_data)) in &edit.dots {
if let Some(weight) = maybe_weight { if let Some(weight) = maybe_new_data {
self.geometry_with_rtree.add_dot_at_index(*dot, *weight); self.geometry_with_rtree.add_dot_at_index(*dot, *weight);
} }
} }
for (seg, (.., maybe_data)) in &edit.segs { for (seg, (.., maybe_new_data)) in &edit.segs {
if let Some(((from, to), weight)) = maybe_data { if let Some(((from, to), weight)) = maybe_new_data {
self.geometry_with_rtree self.geometry_with_rtree
.add_seg_at_index(*seg, *from, *to, *weight); .add_seg_at_index(*seg, *from, *to, *weight);
} }
} }
for (bend, (.., maybe_data)) in &edit.bends { for (bend, (.., maybe_new_data)) in &edit.bends {
if let Some(((from, to, core), weight)) = maybe_data { if let Some(((from, to, core), weight)) = maybe_new_data {
self.geometry_with_rtree self.geometry_with_rtree
.add_bend_at_index(*bend, *from, *to, *core, *weight); .add_bend_at_index(*bend, *from, *to, *core, *weight);
} }
} }
for (compound, (.., maybe_data)) in &edit.compounds { for (compound, (.., maybe_new_data)) in &edit.compounds {
if let Some((members, weight)) = maybe_data { if let Some((members, weight)) = maybe_new_data {
self.geometry_with_rtree self.geometry_with_rtree
.add_compound_at_index(*compound, *weight); .add_compound_at_index(*compound, *weight);