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

View File

@ -62,4 +62,34 @@ impl<
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>
{
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 {
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 {
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 {
if maybe_old_data.is_some() {
self.geometry_with_rtree.remove_seg(*seg);
}
for (dot, ..) in &edit.dots {
self.geometry_with_rtree.remove_dot(*dot);
}
for (dot, (.., maybe_weight)) in &edit.dots {
if let Some(weight) = maybe_weight {
for (dot, (maybe_old_data, ..)) in &edit.dots {
if maybe_old_data.is_some() {
self.geometry_with_rtree.remove_dot(*dot);
}
}
for (dot, (.., maybe_new_data)) in &edit.dots {
if let Some(weight) = maybe_new_data {
self.geometry_with_rtree.add_dot_at_index(*dot, *weight);
}
}
for (seg, (.., maybe_data)) in &edit.segs {
if let Some(((from, to), weight)) = maybe_data {
for (seg, (.., maybe_new_data)) in &edit.segs {
if let Some(((from, to), weight)) = maybe_new_data {
self.geometry_with_rtree
.add_seg_at_index(*seg, *from, *to, *weight);
}
}
for (bend, (.., maybe_data)) in &edit.bends {
if let Some(((from, to, core), weight)) = maybe_data {
for (bend, (.., maybe_new_data)) in &edit.bends {
if let Some(((from, to, core), weight)) = maybe_new_data {
self.geometry_with_rtree
.add_bend_at_index(*bend, *from, *to, *core, *weight);
}
}
for (compound, (.., maybe_data)) in &edit.compounds {
if let Some((members, weight)) = maybe_data {
for (compound, (.., maybe_new_data)) in &edit.compounds {
if let Some((members, weight)) = maybe_new_data {
self.geometry_with_rtree
.add_compound_at_index(*compound, *weight);