egui,autorouter: restore displaying navmesh

This commit is contained in:
Mikolaj Wielgus 2024-07-01 00:50:24 +02:00
parent ee6eeac6d8
commit 2259a75d92
9 changed files with 125 additions and 53 deletions

View File

@ -1,7 +1,7 @@
use petgraph::graph::EdgeIndex; use petgraph::graph::EdgeIndex;
use crate::{ use crate::{
autorouter::{Autorouter, AutorouterError, AutorouterStatus}, autorouter::{invoker::GetMaybeNavmesh, Autorouter, AutorouterError, AutorouterStatus},
board::mesadata::MesadataTrait, board::mesadata::MesadataTrait,
router::{navmesh::Navmesh, route::Route, Router, RouterStatus}, router::{navmesh::Navmesh, route::Route, Router, RouterStatus},
}; };
@ -40,10 +40,15 @@ impl Autoroute {
autorouter: &mut Autorouter<M>, autorouter: &mut Autorouter<M>,
) -> Result<AutorouterStatus, AutorouterError> { ) -> Result<AutorouterStatus, AutorouterError> {
let Some(ref mut route) = self.route else { let Some(ref mut route) = self.route else {
// Shouldn't happen.
return Ok(AutorouterStatus::Finished); return Ok(AutorouterStatus::Finished);
}; };
let (source, target) = autorouter.ratline_endpoints(self.cur_ratline.unwrap()); let Some(cur_ratline) = self.cur_ratline else {
return Ok(AutorouterStatus::Finished);
};
let (source, target) = autorouter.ratline_endpoints(cur_ratline);
let band = { let band = {
let mut router = Router::new(autorouter.board.layout_mut()); let mut router = Router::new(autorouter.board.layout_mut());
@ -63,7 +68,6 @@ impl Autoroute {
.try_set_band_between_nodes(source, target, band); .try_set_band_between_nodes(source, target, band);
let Some(new_ratline) = self.ratlines_iter.next() else { let Some(new_ratline) = self.ratlines_iter.next() else {
self.route = None;
self.cur_ratline = None; self.cur_ratline = None;
return Ok(AutorouterStatus::Finished); return Ok(AutorouterStatus::Finished);
}; };
@ -81,3 +85,9 @@ impl Autoroute {
self.route.as_ref().map(|route| route.navmesh()) self.route.as_ref().map(|route| route.navmesh())
} }
} }
impl GetMaybeNavmesh for Autoroute {
fn maybe_navmesh(&self) -> Option<&Navmesh> {
self.route.as_ref().map(|route| route.navmesh())
}
}

View File

@ -1,4 +1,5 @@
use contracts::debug_requires; use contracts::debug_requires;
use enum_dispatch::enum_dispatch;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use thiserror::Error; use thiserror::Error;
@ -12,8 +13,14 @@ use crate::{
}, },
board::mesadata::MesadataTrait, board::mesadata::MesadataTrait,
layout::via::ViaWeight, layout::via::ViaWeight,
router::navmesh::Navmesh,
}; };
#[enum_dispatch]
pub trait GetMaybeNavmesh {
fn maybe_navmesh(&self) -> Option<&Navmesh>;
}
#[derive(Error, Debug, Clone)] #[derive(Error, Debug, Clone)]
pub enum InvokerError { pub enum InvokerError {
#[error(transparent)] #[error(transparent)]
@ -22,6 +29,7 @@ pub enum InvokerError {
Autorouter(#[from] AutorouterError), Autorouter(#[from] AutorouterError),
} }
#[derive(Debug, Clone, Copy)]
pub enum InvokerStatus { pub enum InvokerStatus {
Running, Running,
Finished, Finished,
@ -33,6 +41,7 @@ pub enum Command {
PlaceVia(ViaWeight), PlaceVia(ViaWeight),
} }
#[enum_dispatch(GetMaybeNavmesh)]
pub enum Execute { pub enum Execute {
Autoroute(Autoroute), Autoroute(Autoroute),
PlaceVia(PlaceVia), PlaceVia(PlaceVia),
@ -46,7 +55,10 @@ impl Execute {
match self.step_catch_err(invoker) { match self.step_catch_err(invoker) {
Ok(InvokerStatus::Running) => Ok(InvokerStatus::Running), Ok(InvokerStatus::Running) => Ok(InvokerStatus::Running),
Ok(InvokerStatus::Finished) => { Ok(InvokerStatus::Finished) => {
invoker.history.do_(invoker.ongoing_command.take().unwrap()); if let Some(command) = invoker.ongoing_command.take() {
invoker.history.do_(command);
}
Ok(InvokerStatus::Finished) Ok(InvokerStatus::Finished)
} }
Err(err) => { Err(err) => {
@ -73,6 +85,39 @@ impl Execute {
} }
} }
pub struct ExecuteWithStatus {
execute: Execute,
maybe_status: Option<InvokerStatus>,
}
impl ExecuteWithStatus {
pub fn new(execute: Execute) -> ExecuteWithStatus {
Self {
execute,
maybe_status: None,
}
}
pub fn step<M: MesadataTrait>(
&mut self,
invoker: &mut Invoker<M>,
) -> Result<InvokerStatus, InvokerError> {
let status = self.execute.step(invoker)?;
self.maybe_status = Some(status);
Ok(status)
}
pub fn maybe_status(&self) -> Option<InvokerStatus> {
self.maybe_status
}
}
impl GetMaybeNavmesh for ExecuteWithStatus {
fn maybe_navmesh(&self) -> Option<&Navmesh> {
self.execute.maybe_navmesh()
}
}
pub struct Invoker<M: MesadataTrait> { pub struct Invoker<M: MesadataTrait> {
autorouter: Autorouter<M>, autorouter: Autorouter<M>,
history: History, history: History,

View File

@ -1,9 +1,11 @@
use crate::{ use crate::{
autorouter::{Autorouter, AutorouterError}, autorouter::{invoker::GetMaybeNavmesh, Autorouter, AutorouterError},
board::mesadata::MesadataTrait, board::mesadata::MesadataTrait,
layout::via::ViaWeight, layout::via::ViaWeight,
router::navmesh::Navmesh,
}; };
#[derive(Debug)]
pub struct PlaceVia { pub struct PlaceVia {
weight: ViaWeight, weight: ViaWeight,
} }
@ -20,3 +22,9 @@ impl PlaceVia {
autorouter.place_via(self.weight) autorouter.place_via(self.weight)
} }
} }
impl GetMaybeNavmesh for PlaceVia {
fn maybe_navmesh(&self) -> Option<&Navmesh> {
None
}
}

View File

@ -13,7 +13,7 @@ use std::{
use topola::{ use topola::{
autorouter::{ autorouter::{
invoker::{Command, Execute, Invoker, InvokerStatus}, invoker::{Command, Execute, ExecuteWithStatus, Invoker, InvokerStatus},
Autorouter, Autorouter,
}, },
drawing::{ drawing::{
@ -56,7 +56,7 @@ pub struct App {
arc_mutex_maybe_invoker: Arc<Mutex<Option<Invoker<SpecctraMesadata>>>>, arc_mutex_maybe_invoker: Arc<Mutex<Option<Invoker<SpecctraMesadata>>>>,
#[serde(skip)] #[serde(skip)]
maybe_execute: Option<Execute>, maybe_execute: Option<ExecuteWithStatus>,
#[serde(skip)] #[serde(skip)]
text_channel: (Sender<String>, Receiver<String>), text_channel: (Sender<String>, Receiver<String>),
@ -129,11 +129,6 @@ impl App {
Ok(status) => status, Ok(status) => status,
Err(err) => return, Err(err) => return,
}; };
if let InvokerStatus::Finished = status {
self.maybe_execute = None;
return;
}
} }
} }
} }
@ -167,6 +162,7 @@ impl eframe::App for App {
ctx, ctx,
&self.top, &self.top,
&mut self.arc_mutex_maybe_invoker.lock().unwrap(), &mut self.arc_mutex_maybe_invoker.lock().unwrap(),
&mut self.maybe_execute,
&mut self.maybe_overlay, &mut self.maybe_overlay,
&self.maybe_layers, &self.maybe_layers,
); );

View File

@ -4,7 +4,7 @@ use std::{
}; };
use topola::{ use topola::{
autorouter::invoker::{Command, Execute, Invoker, InvokerStatus}, autorouter::invoker::{Command, Execute, ExecuteWithStatus, Invoker, InvokerStatus},
specctra::mesadata::SpecctraMesadata, specctra::mesadata::SpecctraMesadata,
}; };
@ -33,7 +33,7 @@ impl Top {
ctx: &egui::Context, ctx: &egui::Context,
sender: Sender<String>, sender: Sender<String>,
arc_mutex_maybe_invoker: Arc<Mutex<Option<Invoker<SpecctraMesadata>>>>, arc_mutex_maybe_invoker: Arc<Mutex<Option<Invoker<SpecctraMesadata>>>>,
maybe_execute: &mut Option<Execute>, maybe_execute: &mut Option<ExecuteWithStatus>,
maybe_overlay: &Option<Overlay>, maybe_overlay: &Option<Overlay>,
) { ) {
egui::TopBottomPanel::top("top_panel").show(ctx, |ui| { egui::TopBottomPanel::top("top_panel").show(ctx, |ui| {
@ -116,14 +116,17 @@ impl Top {
ui.separator(); ui.separator();
if ui.button("Autoroute").clicked() { if ui.button("Autoroute").clicked() {
if maybe_execute.is_none() { if maybe_execute.as_mut().map_or(true, |execute| {
matches!(execute.maybe_status(), Some(InvokerStatus::Finished))
}) {
if let (Some(invoker), Some(ref overlay)) = ( if let (Some(invoker), Some(ref overlay)) = (
arc_mutex_maybe_invoker.lock().unwrap().as_mut(), arc_mutex_maybe_invoker.lock().unwrap().as_mut(),
maybe_overlay, maybe_overlay,
) { ) {
let selection = overlay.selection().clone(); let selection = overlay.selection().clone();
maybe_execute maybe_execute.insert(ExecuteWithStatus::new(
.insert(invoker.execute_walk(Command::Autoroute(selection))); invoker.execute_walk(Command::Autoroute(selection)),
));
} }
} }
} }

View File

@ -1,7 +1,7 @@
use geo::point; use geo::point;
use petgraph::visit::{EdgeRef, IntoEdgeReferences}; use petgraph::visit::{EdgeRef, IntoEdgeReferences};
use topola::{ use topola::{
autorouter::invoker::{Command, Invoker}, autorouter::invoker::{Command, ExecuteWithStatus, GetMaybeNavmesh, Invoker},
board::mesadata::MesadataTrait, board::mesadata::MesadataTrait,
drawing::{ drawing::{
graph::{MakePrimitive, PrimitiveIndex}, graph::{MakePrimitive, PrimitiveIndex},
@ -31,6 +31,7 @@ impl Viewport {
ctx: &egui::Context, ctx: &egui::Context,
top: &Top, top: &Top,
maybe_invoker: &mut Option<Invoker<SpecctraMesadata>>, maybe_invoker: &mut Option<Invoker<SpecctraMesadata>>,
maybe_execute: &mut Option<ExecuteWithStatus>,
maybe_overlay: &mut Option<Overlay>, maybe_overlay: &mut Option<Overlay>,
maybe_layers: &Option<Layers>, maybe_layers: &Option<Layers>,
) -> egui::Rect { ) -> egui::Rect {
@ -152,48 +153,50 @@ impl Viewport {
} }
} }
/*if top.show_navmesh { if top.show_navmesh {
if let Some(navmesh) = &shared_data.navmesh { if let Some(execute) = maybe_execute {
for edge in navmesh.graph().edge_references() { if let Some(navmesh) = execute.maybe_navmesh() {
let from = PrimitiveIndex::from(navmesh.graph().node_weight(edge.source()).unwrap().node) for edge in navmesh.graph().edge_references() {
.primitive(board.layout().drawing()) let from = PrimitiveIndex::from(navmesh.graph().node_weight(edge.source()).unwrap().node)
.shape() .primitive(board.layout().drawing())
.center(); .shape()
let to = PrimitiveIndex::from(navmesh.graph().node_weight(edge.target()).unwrap().node) .center();
.primitive(board.layout().drawing()) let to = PrimitiveIndex::from(navmesh.graph().node_weight(edge.target()).unwrap().node)
.shape() .primitive(board.layout().drawing())
.center(); .shape()
.center();
let stroke = 'blk: { let stroke = 'blk: {
if let (Some(source_pos), Some(target_pos)) = ( /*if let (Some(source_pos), Some(target_pos)) = (
shared_data shared_data
.path .path
.iter() .iter()
.position(|node| *node == navmesh.graph().node_weight(edge.source()).unwrap().node), .position(|node| *node == navmesh.graph().node_weight(edge.source()).unwrap().node),
shared_data shared_data
.path .path
.iter() .iter()
.position(|node| *node == navmesh.graph().node_weight(edge.target()).unwrap().node), .position(|node| *node == navmesh.graph().node_weight(edge.target()).unwrap().node),
) { ) {
if target_pos == source_pos + 1 if target_pos == source_pos + 1
|| source_pos == target_pos + 1 || source_pos == target_pos + 1
{ {
break 'blk egui::Stroke::new( break 'blk egui::Stroke::new(
5.0, 5.0,
egui::Color32::from_rgb(250, 250, 0), egui::Color32::from_rgb(250, 250, 0),
); );
} }
} }*/
egui::Stroke::new(1.0, egui::Color32::from_rgb(125, 125, 125)) egui::Stroke::new(1.0, egui::Color32::from_rgb(125, 125, 125))
}; };
painter.paint_edge(from, to, stroke); painter.paint_edge(from, to, stroke);
}
} }
} }
} }
for ghost in shared_data.ghosts.iter() { /*for ghost in shared_data.ghosts.iter() {
painter.paint_primitive(&ghost, egui::Color32::from_rgb(75, 75, 150)); painter.paint_primitive(&ghost, egui::Color32::from_rgb(75, 75, 150));
} }

View File

@ -57,6 +57,7 @@ impl<K: PartialOrd, T> Ord for MinScored<K, T> {
} }
} }
#[derive(Debug)]
pub struct PathTracker<G> pub struct PathTracker<G>
where where
G: GraphBase, G: GraphBase,
@ -111,6 +112,7 @@ where
fn estimate_cost(&mut self, graph: &G, node: G::NodeId) -> K; fn estimate_cost(&mut self, graph: &G, node: G::NodeId) -> K;
} }
#[derive(Debug)]
pub struct Astar<G, K> pub struct Astar<G, K>
where where
G: GraphBase, G: GraphBase,
@ -131,6 +133,7 @@ pub enum AstarError {
NotFound, NotFound,
} }
#[derive(Debug)]
pub enum AstarStatus<G, K, R> pub enum AstarStatus<G, K, R>
where where
G: GraphBase, G: GraphBase,

View File

@ -31,6 +31,7 @@ use crate::{
}, },
}; };
#[derive(Debug)]
pub struct Route { pub struct Route {
astar: Astar<Navmesh, f64>, astar: Astar<Navmesh, f64>,
trace: Trace, trace: Trace,

View File

@ -30,11 +30,13 @@ pub enum RouterError {
Astar(#[from] AstarError), Astar(#[from] AstarError),
} }
#[derive(Debug)]
pub enum RouterStatus { pub enum RouterStatus {
Running, Running,
Finished(BandFirstSegIndex), Finished(BandFirstSegIndex),
} }
#[derive(Debug)]
pub struct RouterAstarStrategy<'a, R: RulesTrait> { pub struct RouterAstarStrategy<'a, R: RulesTrait> {
pub tracer: Tracer<'a, R>, pub tracer: Tracer<'a, R>,
pub trace: &'a mut Trace, pub trace: &'a mut Trace,
@ -142,6 +144,7 @@ impl<'a, R: RulesTrait> AstarStrategy<Navmesh, f64, BandFirstSegIndex>
} }
} }
#[derive(Debug)]
pub struct Router<'a, R: RulesTrait> { pub struct Router<'a, R: RulesTrait> {
layout: &'a mut Layout<R>, layout: &'a mut Layout<R>,
} }