diff --git a/src/autorouter/execute.rs b/src/autorouter/execute.rs index 879bb5c..2d4e34a 100644 --- a/src/autorouter/execute.rs +++ b/src/autorouter/execute.rs @@ -1,22 +1,12 @@ use enum_dispatch::enum_dispatch; use serde::{Deserialize, Serialize}; -use crate::{ - board::mesadata::AccessMesadata, - drawing::graph::PrimitiveIndex, - geometry::primitive::PrimitiveShape, - layout::via::ViaWeight, - router::{navmesh::Navmesh, trace::Trace}, - step::Step, -}; +use crate::{board::mesadata::AccessMesadata, layout::via::ViaWeight, step::Step}; use super::{ autoroute::{Autoroute, AutorouteStatus}, compare_detours::{CompareDetours, CompareDetoursStatus}, - invoker::{ - GetGhosts, GetMaybeNavmesh, GetMaybeTrace, GetObstacles, Invoker, InvokerError, - InvokerStatus, - }, + invoker::{Invoker, InvokerError, InvokerStatus}, measure_length::MeasureLength, place_via::PlaceVia, remove_bands::RemoveBands, diff --git a/src/bin/topola-egui/activity.rs b/src/bin/topola-egui/activity.rs index a27b6fc..d454599 100644 --- a/src/bin/topola-egui/activity.rs +++ b/src/bin/topola-egui/activity.rs @@ -1,3 +1,4 @@ +use thiserror::Error; use topola::{ autorouter::{ execute::Execute, @@ -10,56 +11,140 @@ use topola::{ drawing::graph::PrimitiveIndex, geometry::primitive::PrimitiveShape, router::{navmesh::Navmesh, trace::Trace}, + specctra::mesadata::SpecctraMesadata, step::Step, }; +#[derive(Error, Debug, Clone)] +pub enum ActivityError { + #[error(transparent)] + Invoker(#[from] InvokerError), +} + +#[derive(Debug, Clone)] +pub enum ActivityStatus { + Running, + Finished(String), +} + +impl From for ActivityStatus { + fn from(status: InvokerStatus) -> Self { + match status { + InvokerStatus::Running => ActivityStatus::Running, + InvokerStatus::Finished(msg) => ActivityStatus::Finished(msg), + } + } +} + +impl TryInto<()> for ActivityStatus { + type Error = (); + fn try_into(self) -> Result<(), ()> { + match self { + ActivityStatus::Running => Err(()), + ActivityStatus::Finished(..) => Ok(()), + } + } +} + +pub enum Activity { + // There will be another variant for interactive activities here soon. (TODO) + Execute(Execute), +} + +impl Step, ActivityStatus, ActivityError, ()> for Activity { + fn step( + &mut self, + invoker: &mut Invoker, + ) -> Result { + match self { + Activity::Execute(execute) => Ok(execute.step(invoker)?.into()), + } + } +} + +impl GetMaybeNavmesh for Activity { + /// Implemented manually instead of with `enum_dispatch` because it doesn't work across crates. + fn maybe_navmesh(&self) -> Option<&Navmesh> { + match self { + Activity::Execute(execute) => execute.maybe_navmesh(), + } + } +} + +impl GetMaybeTrace for Activity { + /// Implemented manually instead of with `enum_dispatch` because it doesn't work across crates. + fn maybe_trace(&self) -> Option<&Trace> { + match self { + Activity::Execute(execute) => execute.maybe_trace(), + } + } +} + +impl GetGhosts for Activity { + /// Implemented manually instead of with `enum_dispatch` because it doesn't work across crates. + fn ghosts(&self) -> &[PrimitiveShape] { + match self { + Activity::Execute(execute) => execute.ghosts(), + } + } +} + +impl GetObstacles for Activity { + /// Implemented manually instead of with `enum_dispatch` because it doesn't work across crates. + fn obstacles(&self) -> &[PrimitiveIndex] { + match self { + Activity::Execute(execute) => execute.obstacles(), + } + } +} + pub struct ActivityWithStatus { - execute: Execute, - maybe_status: Option, + activity: Activity, + maybe_status: Option, } impl ActivityWithStatus { pub fn new_execute(execute: Execute) -> ActivityWithStatus { Self { - execute, + activity: Activity::Execute(execute), maybe_status: None, } } - pub fn step( + pub fn step( &mut self, - invoker: &mut Invoker, - ) -> Result { - let status = self.execute.step(invoker)?; + invoker: &mut Invoker, + ) -> Result { + let status = self.activity.step(invoker)?; self.maybe_status = Some(status.clone()); - Ok(status) + Ok(status.into()) } - pub fn maybe_status(&self) -> Option { + pub fn maybe_status(&self) -> Option { self.maybe_status.clone() } } impl GetMaybeNavmesh for ActivityWithStatus { fn maybe_navmesh(&self) -> Option<&Navmesh> { - self.execute.maybe_navmesh() + self.activity.maybe_navmesh() } } impl GetMaybeTrace for ActivityWithStatus { fn maybe_trace(&self) -> Option<&Trace> { - self.execute.maybe_trace() + self.activity.maybe_trace() } } impl GetGhosts for ActivityWithStatus { fn ghosts(&self) -> &[PrimitiveShape] { - self.execute.ghosts() + self.activity.ghosts() } } impl GetObstacles for ActivityWithStatus { fn obstacles(&self) -> &[PrimitiveIndex] { - self.execute.obstacles() + self.activity.obstacles() } } diff --git a/src/bin/topola-egui/app.rs b/src/bin/topola-egui/app.rs index 7da838a..ef3c8bf 100644 --- a/src/bin/topola-egui/app.rs +++ b/src/bin/topola-egui/app.rs @@ -13,10 +13,7 @@ use std::{ use unic_langid::{langid, LanguageIdentifier}; use topola::{ - autorouter::{ - invoker::{Invoker, InvokerStatus}, - Autorouter, - }, + autorouter::{invoker::Invoker, Autorouter}, drawing::{ dot::FixedDotIndex, graph::{MakePrimitive, PrimitiveIndex}, @@ -42,8 +39,15 @@ use topola::{ }; use crate::{ - activity::ActivityWithStatus, bottom::Bottom, file_receiver::FileReceiver, layers::Layers, - overlay::Overlay, painter::Painter, top::Top, translator::Translator, viewport::Viewport, + activity::{ActivityStatus, ActivityWithStatus}, + bottom::Bottom, + file_receiver::FileReceiver, + layers::Layers, + overlay::Overlay, + painter::Painter, + top::Top, + translator::Translator, + viewport::Viewport, }; /// Deserialize/Serialize is needed to persist app state between restarts. @@ -159,8 +163,8 @@ impl App { if let Some(ref mut activity) = self.maybe_activity { match activity.step(invoker) { - Ok(InvokerStatus::Running) => return true, - Ok(InvokerStatus::Finished(..)) => return false, + Ok(ActivityStatus::Running) => return true, + Ok(ActivityStatus::Finished(..)) => return false, Err(err) => return false, } } diff --git a/src/bin/topola-egui/bottom.rs b/src/bin/topola-egui/bottom.rs index 9bac24a..b64600f 100644 --- a/src/bin/topola-egui/bottom.rs +++ b/src/bin/topola-egui/bottom.rs @@ -1,6 +1,10 @@ use topola::autorouter::invoker::InvokerStatus; -use crate::{activity::ActivityWithStatus, translator::Translator, viewport::Viewport}; +use crate::{ + activity::{ActivityStatus, ActivityWithStatus}, + translator::Translator, + viewport::Viewport, +}; pub struct Bottom {} @@ -23,7 +27,7 @@ impl Bottom { let mut message = String::from(""); if let Some(activity) = maybe_activity { - if let Some(InvokerStatus::Finished(msg)) = activity.maybe_status() { + if let Some(ActivityStatus::Finished(msg)) = activity.maybe_status() { message = msg; } } diff --git a/src/bin/topola-egui/top.rs b/src/bin/topola-egui/top.rs index 081c349..6bd0c28 100644 --- a/src/bin/topola-egui/top.rs +++ b/src/bin/topola-egui/top.rs @@ -16,7 +16,7 @@ use topola::{ use crate::{ action::{Action, Switch, Trigger}, - activity::ActivityWithStatus, + activity::{ActivityStatus, ActivityWithStatus}, app::execute, file_sender::FileSender, overlay::Overlay, @@ -292,7 +292,7 @@ impl Top { ctx.send_viewport_cmd(egui::ViewportCommand::Close); } else if autoroute.consume_key_triggered(ctx, ui) { if maybe_activity.as_mut().map_or(true, |activity| { - matches!(activity.maybe_status(), Some(InvokerStatus::Finished(..))) + matches!(activity.maybe_status(), Some(ActivityStatus::Finished(..))) }) { if let (Some(invoker), Some(ref mut overlay)) = ( arc_mutex_maybe_invoker.lock().unwrap().as_mut(), @@ -311,7 +311,7 @@ impl Top { } else if place_via.consume_key_enabled(ctx, ui, &mut self.is_placing_via) { } else if remove_bands.consume_key_triggered(ctx, ui) { if maybe_activity.as_mut().map_or(true, |activity| { - matches!(activity.maybe_status(), Some(InvokerStatus::Finished(..))) + matches!(activity.maybe_status(), Some(ActivityStatus::Finished(..))) }) { if let (Some(invoker), Some(ref mut overlay)) = ( arc_mutex_maybe_invoker.lock().unwrap().as_mut(), @@ -328,7 +328,7 @@ impl Top { } } else if measure_length.consume_key_triggered(ctx, ui) { if maybe_activity.as_mut().map_or(true, |activity| { - matches!(activity.maybe_status(), Some(InvokerStatus::Finished(..))) + matches!(activity.maybe_status(), Some(ActivityStatus::Finished(..))) }) { if let (Some(invoker), Some(ref mut overlay)) = ( arc_mutex_maybe_invoker.lock().unwrap().as_mut(), @@ -353,7 +353,7 @@ impl Top { } } else if compare_detours.consume_key_triggered(ctx, ui) { if maybe_activity.as_mut().map_or(true, |activity| { - matches!(activity.maybe_status(), Some(InvokerStatus::Finished(..))) + matches!(activity.maybe_status(), Some(ActivityStatus::Finished(..))) }) { if let (Some(invoker), Some(ref mut overlay)) = ( arc_mutex_maybe_invoker.lock().unwrap().as_mut(),