egui,autorouter: make detour comparison invokable from GUI

This commit is contained in:
Mikolaj Wielgus 2024-08-05 13:14:56 +02:00
parent b2c9305cea
commit 47d8e82344
5 changed files with 60 additions and 33 deletions

View File

@ -12,7 +12,7 @@ use crate::{
use super::{ use super::{
autoroute::Autoroute, autoroute::Autoroute,
compare::Compare, compare_detours::CompareDetours,
place_via::PlaceVia, place_via::PlaceVia,
ratsnest::{Ratsnest, RatvertexIndex}, ratsnest::{Ratsnest, RatvertexIndex},
remove_bands::RemoveBands, remove_bands::RemoveBands,
@ -88,21 +88,21 @@ impl<M: AccessMesadata> Autorouter<M> {
todo!(); todo!();
} }
pub fn compare(&mut self, selection: &PinSelection) -> Result<Compare, AutorouterError> { pub fn compare(&mut self, selection: &PinSelection) -> Result<CompareDetours, AutorouterError> {
self.compare_ratlines(self.selected_ratlines(selection)) self.compare_ratlines(self.selected_ratlines(selection))
} }
fn compare_ratlines( fn compare_ratlines(
&mut self, &mut self,
ratlines: Vec<EdgeIndex<usize>>, ratlines: Vec<EdgeIndex<usize>>,
) -> Result<Compare, AutorouterError> { ) -> Result<CompareDetours, AutorouterError> {
let ratline1 = *ratlines let ratline1 = *ratlines
.get(0) .get(0)
.ok_or(AutorouterError::NeedExactlyTwoRatlines)?; .ok_or(AutorouterError::NeedExactlyTwoRatlines)?;
let ratline2 = *ratlines let ratline2 = *ratlines
.get(1) .get(1)
.ok_or(AutorouterError::NeedExactlyTwoRatlines)?; .ok_or(AutorouterError::NeedExactlyTwoRatlines)?;
Compare::new(self, ratline1, ratline2) CompareDetours::new(self, ratline1, ratline2)
} }
pub fn ratline_endpoints( pub fn ratline_endpoints(

View File

@ -15,22 +15,22 @@ use super::{
Autorouter, AutorouterError, Autorouter, AutorouterError,
}; };
pub enum CompareStatus { pub enum CompareDetoursStatus {
Running, Running,
Finished(f64), Finished(f64),
} }
impl TryInto<f64> for CompareStatus { impl TryInto<f64> for CompareDetoursStatus {
type Error = (); type Error = ();
fn try_into(self) -> Result<f64, ()> { fn try_into(self) -> Result<f64, ()> {
match self { match self {
CompareStatus::Running => Err(()), CompareDetoursStatus::Running => Err(()),
CompareStatus::Finished(delta) => Ok(delta), CompareDetoursStatus::Finished(delta) => Ok(delta),
} }
} }
} }
pub struct Compare { pub struct CompareDetours {
autoroute: Autoroute, autoroute: Autoroute,
next_autoroute: Option<Autoroute>, next_autoroute: Option<Autoroute>,
ratline1: EdgeIndex<usize>, ratline1: EdgeIndex<usize>,
@ -39,7 +39,7 @@ pub struct Compare {
total_length2: Option<f64>, total_length2: Option<f64>,
} }
impl Compare { impl CompareDetours {
pub fn new( pub fn new(
autorouter: &mut Autorouter<impl AccessMesadata>, autorouter: &mut Autorouter<impl AccessMesadata>,
ratline1: EdgeIndex<usize>, ratline1: EdgeIndex<usize>,
@ -58,10 +58,15 @@ impl Compare {
// XXX: Do we really need this to be a stepper? We don't use at the moment, as sorting functions // XXX: Do we really need this to be a stepper? We don't use at the moment, as sorting functions
// aren't steppable either. It may be useful for debugging later on tho. // aren't steppable either. It may be useful for debugging later on tho.
impl<M: AccessMesadata> Step<Autorouter<M>, CompareStatus, AutorouterError, f64> for Compare { impl<M: AccessMesadata> Step<Autorouter<M>, CompareDetoursStatus, AutorouterError, f64>
fn step(&mut self, autorouter: &mut Autorouter<M>) -> Result<CompareStatus, AutorouterError> { for CompareDetours
{
fn step(
&mut self,
autorouter: &mut Autorouter<M>,
) -> Result<CompareDetoursStatus, AutorouterError> {
match self.autoroute.step(autorouter)? { match self.autoroute.step(autorouter)? {
AutorouteStatus::Running => Ok(CompareStatus::Running), AutorouteStatus::Running => Ok(CompareDetoursStatus::Running),
AutorouteStatus::Routed(band_termseg) => { AutorouteStatus::Routed(band_termseg) => {
let length = band_termseg let length = band_termseg
.ref_(autorouter.board.layout().drawing()) .ref_(autorouter.board.layout().drawing())
@ -75,18 +80,18 @@ impl<M: AccessMesadata> Step<Autorouter<M>, CompareStatus, AutorouterError, f64>
panic!(); panic!();
} }
Ok(CompareStatus::Running) Ok(CompareDetoursStatus::Running)
} }
AutorouteStatus::Finished => { AutorouteStatus::Finished => {
if let Some(next_autoroute) = self.next_autoroute.take() { if let Some(next_autoroute) = self.next_autoroute.take() {
autorouter.undo_autoroute_ratlines(vec![self.ratline1, self.ratline2]); autorouter.undo_autoroute_ratlines(vec![self.ratline1, self.ratline2]);
self.autoroute = next_autoroute; self.autoroute = next_autoroute;
Ok(CompareStatus::Running) Ok(CompareDetoursStatus::Running)
} else { } else {
autorouter.undo_autoroute_ratlines(vec![self.ratline2, self.ratline1]); autorouter.undo_autoroute_ratlines(vec![self.ratline2, self.ratline1]);
Ok(CompareStatus::Finished( Ok(CompareDetoursStatus::Finished(
self.total_length1.unwrap() - self.total_length2.unwrap(), self.total_length1.unwrap() - self.total_length2.unwrap(),
)) ))
} }
@ -95,25 +100,25 @@ impl<M: AccessMesadata> Step<Autorouter<M>, CompareStatus, AutorouterError, f64>
} }
} }
impl GetMaybeNavmesh for Compare { impl GetMaybeNavmesh for CompareDetours {
fn maybe_navmesh(&self) -> Option<&Navmesh> { fn maybe_navmesh(&self) -> Option<&Navmesh> {
self.autoroute.maybe_navmesh() self.autoroute.maybe_navmesh()
} }
} }
impl GetMaybeTrace for Compare { impl GetMaybeTrace for CompareDetours {
fn maybe_trace(&self) -> Option<&Trace> { fn maybe_trace(&self) -> Option<&Trace> {
self.autoroute.maybe_trace() self.autoroute.maybe_trace()
} }
} }
impl GetGhosts for Compare { impl GetGhosts for CompareDetours {
fn ghosts(&self) -> &[PrimitiveShape] { fn ghosts(&self) -> &[PrimitiveShape] {
self.autoroute.ghosts() self.autoroute.ghosts()
} }
} }
impl GetObstacles for Compare { impl GetObstacles for CompareDetours {
fn obstacles(&self) -> &[PrimitiveIndex] { fn obstacles(&self) -> &[PrimitiveIndex] {
self.autoroute.obstacles() self.autoroute.obstacles()
} }

View File

@ -14,7 +14,7 @@ use crate::{
use super::{ use super::{
autoroute::{Autoroute, AutorouteStatus}, autoroute::{Autoroute, AutorouteStatus},
compare::{Compare, CompareStatus}, compare_detours::{CompareDetours, CompareDetoursStatus},
history::{History, HistoryError}, history::{History, HistoryError},
place_via::PlaceVia, place_via::PlaceVia,
remove_bands::RemoveBands, remove_bands::RemoveBands,
@ -71,7 +71,7 @@ pub enum Command {
Autoroute(PinSelection), Autoroute(PinSelection),
PlaceVia(ViaWeight), PlaceVia(ViaWeight),
RemoveBands(BandSelection), RemoveBands(BandSelection),
Compare(PinSelection), CompareDetours(PinSelection),
} }
#[enum_dispatch(GetMaybeNavmesh, GetMaybeTrace, GetGhosts, GetObstacles)] #[enum_dispatch(GetMaybeNavmesh, GetMaybeTrace, GetGhosts, GetObstacles)]
@ -79,7 +79,7 @@ pub enum Execute {
Autoroute(Autoroute), Autoroute(Autoroute),
PlaceVia(PlaceVia), PlaceVia(PlaceVia),
RemoveBands(RemoveBands), RemoveBands(RemoveBands),
Compare(Compare), CompareDetours(CompareDetours),
} }
impl Execute { impl Execute {
@ -101,9 +101,9 @@ impl Execute {
remove_bands.doit(&mut invoker.autorouter)?; remove_bands.doit(&mut invoker.autorouter)?;
Ok(InvokerStatus::Finished) Ok(InvokerStatus::Finished)
} }
Execute::Compare(compare) => match compare.step(&mut invoker.autorouter)? { Execute::CompareDetours(compare) => match compare.step(&mut invoker.autorouter)? {
CompareStatus::Running => Ok(InvokerStatus::Running), CompareDetoursStatus::Running => Ok(InvokerStatus::Running),
CompareStatus::Finished(delta) => Ok(InvokerStatus::Finished), CompareDetoursStatus::Finished(delta) => Ok(InvokerStatus::Finished),
}, },
} }
} }
@ -238,9 +238,9 @@ impl<M: AccessMesadata> Invoker<M> {
Command::RemoveBands(selection) => Ok::<Execute, InvokerError>(Execute::RemoveBands( Command::RemoveBands(selection) => Ok::<Execute, InvokerError>(Execute::RemoveBands(
self.autorouter.remove_bands(selection)?, self.autorouter.remove_bands(selection)?,
)), )),
Command::Compare(selection) => { Command::CompareDetours(selection) => Ok::<Execute, InvokerError>(
Ok::<Execute, InvokerError>(Execute::Compare(self.autorouter.compare(selection)?)) Execute::CompareDetours(self.autorouter.compare(selection)?),
} ),
} }
} }
@ -252,7 +252,7 @@ impl<M: AccessMesadata> Invoker<M> {
Command::Autoroute(ref selection) => self.autorouter.undo_autoroute(selection), Command::Autoroute(ref selection) => self.autorouter.undo_autoroute(selection),
Command::PlaceVia(weight) => self.autorouter.undo_place_via(*weight), Command::PlaceVia(weight) => self.autorouter.undo_place_via(*weight),
Command::RemoveBands(ref selection) => self.autorouter.undo_remove_bands(selection), Command::RemoveBands(ref selection) => self.autorouter.undo_remove_bands(selection),
Command::Compare(..) => (), Command::CompareDetours(..) => (),
} }
Ok::<(), InvokerError>(self.history.undo()?) Ok::<(), InvokerError>(self.history.undo()?)

View File

@ -1,6 +1,6 @@
pub mod autoroute; pub mod autoroute;
mod autorouter; mod autorouter;
pub mod compare; pub mod compare_detours;
pub mod history; pub mod history;
pub mod invoker; pub mod invoker;
pub mod place_via; pub mod place_via;

View File

@ -80,6 +80,11 @@ impl Top {
egui::Modifiers::NONE, egui::Modifiers::NONE,
egui::Key::Delete, egui::Key::Delete,
)); ));
let mut compare_detours = Trigger::new(Action::new(
"Compare Detours",
egui::Modifiers::NONE,
egui::Key::Minus,
));
let mut undo = Trigger::new(Action::new("Undo", egui::Modifiers::CTRL, egui::Key::Z)); let mut undo = Trigger::new(Action::new("Undo", egui::Modifiers::CTRL, egui::Key::Z));
let mut redo = Trigger::new(Action::new("Redo", egui::Modifiers::CTRL, egui::Key::Y)); let mut redo = Trigger::new(Action::new("Redo", egui::Modifiers::CTRL, egui::Key::Y));
@ -123,6 +128,9 @@ impl Top {
ui.checkbox(&mut self.show_navmesh, "Show Navmesh"); ui.checkbox(&mut self.show_navmesh, "Show Navmesh");
ui.checkbox(&mut self.show_bboxes, "Show BBoxes"); ui.checkbox(&mut self.show_bboxes, "Show BBoxes");
ui.checkbox(&mut self.show_origin_destination, "Show OriginDestination"); ui.checkbox(&mut self.show_origin_destination, "Show OriginDestination");
ui.separator();
compare_detours.button(ctx, ui);
}); });
ui.separator(); ui.separator();
@ -240,10 +248,24 @@ impl Top {
invoker.undo(); invoker.undo();
} }
} else if redo.consume_key_triggered(ctx, ui) { } else if redo.consume_key_triggered(ctx, ui) {
if let Some(ref mut invoker) = arc_mutex_maybe_invoker.lock().unwrap().as_mut() if let Some(invoker) = arc_mutex_maybe_invoker.lock().unwrap().as_mut() {
{
invoker.redo(); invoker.redo();
} }
} else if compare_detours.consume_key_triggered(ctx, ui) {
if maybe_execute.as_mut().map_or(true, |execute| {
matches!(execute.maybe_status(), Some(InvokerStatus::Finished))
}) {
if let (Some(invoker), Some(ref mut overlay)) = (
arc_mutex_maybe_invoker.lock().unwrap().as_mut(),
maybe_overlay,
) {
let selection = overlay.selection().clone();
overlay.clear_selection();
maybe_execute.insert(ExecuteWithStatus::new(invoker.execute_stepper(
Command::CompareDetours(selection.pin_selection),
)?));
}
}
} }
Ok::<(), InvokerError>(()) Ok::<(), InvokerError>(())