egui: perform routing in separate thread or task

This commit is contained in:
Mikolaj Wielgus 2024-05-03 19:50:38 +02:00
parent 682f179cad
commit 4144ee361f
1 changed files with 99 additions and 87 deletions

View File

@ -3,7 +3,10 @@ use geo::point;
use petgraph::visit::{EdgeRef, IntoEdgeReferences}; use petgraph::visit::{EdgeRef, IntoEdgeReferences};
use std::{ use std::{
future::Future, future::Future,
sync::mpsc::{channel, Receiver, Sender}, sync::{
mpsc::{channel, Receiver, Sender},
Arc, Mutex,
},
}; };
use topola::{ use topola::{
@ -40,7 +43,7 @@ pub struct App {
overlay: Option<Overlay>, overlay: Option<Overlay>,
#[serde(skip)] #[serde(skip)]
autorouter: Option<Autorouter<DsnRules>>, autorouter: Option<Arc<Mutex<Autorouter<DsnRules>>>>,
#[serde(skip)] #[serde(skip)]
text_channel: (Sender<String>, Receiver<String>), text_channel: (Sender<String>, Receiver<String>),
@ -108,14 +111,14 @@ impl eframe::App for App {
let design = DsnDesign::load_from_string(file_contents).unwrap(); let design = DsnDesign::load_from_string(file_contents).unwrap();
let layout = design.make_layout(); let layout = design.make_layout();
self.overlay = Some(Overlay::new(&layout).unwrap()); self.overlay = Some(Overlay::new(&layout).unwrap());
self.autorouter = Some(Autorouter::new(layout).unwrap()); self.autorouter = Some(Arc::new(Mutex::new(Autorouter::new(layout).unwrap())));
} }
} else { } else {
if let Ok(path) = self.text_channel.1.try_recv() { if let Ok(path) = self.text_channel.1.try_recv() {
let design = DsnDesign::load_from_file(&path).unwrap(); let design = DsnDesign::load_from_file(&path).unwrap();
let layout = design.make_layout(); let layout = design.make_layout();
self.overlay = Some(Overlay::new(&layout).unwrap()); self.overlay = Some(Overlay::new(&layout).unwrap());
self.autorouter = Some(Autorouter::new(layout).unwrap()); self.autorouter = Some(Arc::new(Mutex::new(Autorouter::new(layout).unwrap())));
} }
} }
@ -150,8 +153,12 @@ impl eframe::App for App {
ui.separator(); ui.separator();
if ui.button("Autoroute").clicked() { if ui.button("Autoroute").clicked() {
if let Some(ref mut autorouter) = &mut self.autorouter { if let Some(autorouter_arc_mutex) = &self.autorouter {
autorouter.autoroute(&mut EmptyRouterObserver {}); let autorouter_mutex = autorouter_arc_mutex.clone();
execute(async move {
let mut autorouter = autorouter_mutex.lock().unwrap();
autorouter.autoroute(&mut EmptyRouterObserver {});
});
} }
} }
@ -192,97 +199,102 @@ impl eframe::App for App {
let transform = egui::emath::RectTransform::from_to(self.from_rect, viewport_rect); let transform = egui::emath::RectTransform::from_to(self.from_rect, viewport_rect);
let mut painter = Painter::new(ui, transform); let mut painter = Painter::new(ui, transform);
if let (Some(autorouter), Some(overlay)) = (&self.autorouter, &mut self.overlay) { if let (Some(autorouter_arc_mutex), Some(overlay)) =
if ctx.input(|i| i.pointer.any_click()) { (&self.autorouter, &mut self.overlay)
overlay.click( {
autorouter.router().layout(), if let Ok(autorouter) = autorouter_arc_mutex.try_lock() {
point! {x: latest_pos.x as f64, y: -latest_pos.y as f64}, if ctx.input(|i| i.pointer.any_click()) {
); overlay.click(
} autorouter.router().layout(),
point! {x: latest_pos.x as f64, y: -latest_pos.y as f64},
);
}
for primitive in autorouter for primitive in autorouter
.router() .router()
.layout() .layout()
.drawing() .drawing()
.layer_primitive_nodes(1) .layer_primitive_nodes(1)
{
let shape = primitive
.primitive(autorouter.router().layout().drawing())
.shape();
let color = if overlay
.selection()
.contains(&GenericNode::Primitive(primitive))
{ {
egui::Color32::from_rgb(100, 100, 255) let shape = primitive
} else { .primitive(autorouter.router().layout().drawing())
egui::Color32::from_rgb(52, 52, 200) .shape();
};
painter.paint_shape(&shape, color);
}
for zone in autorouter.router().layout().layer_zone_nodes(1) { let color = if overlay
let color = if overlay.selection().contains(&GenericNode::Compound(zone)) { .selection()
egui::Color32::from_rgb(100, 100, 255) .contains(&GenericNode::Primitive(primitive))
} else { {
egui::Color32::from_rgb(52, 52, 200) egui::Color32::from_rgb(100, 100, 255)
}; } else {
painter.paint_polygon( egui::Color32::from_rgb(52, 52, 200)
&autorouter.router().layout().zone(zone).shape().polygon, };
color, painter.paint_shape(&shape, color);
) }
}
for primitive in autorouter for zone in autorouter.router().layout().layer_zone_nodes(1) {
.router() let color =
.layout() if overlay.selection().contains(&GenericNode::Compound(zone)) {
.drawing() egui::Color32::from_rgb(100, 100, 255)
.layer_primitive_nodes(0) } else {
{ egui::Color32::from_rgb(52, 52, 200)
let shape = primitive };
.primitive(autorouter.router().layout().drawing()) painter.paint_polygon(
.shape(); &autorouter.router().layout().zone(zone).shape().polygon,
color,
)
}
let color = if overlay for primitive in autorouter
.selection() .router()
.contains(&GenericNode::Primitive(primitive)) .layout()
.drawing()
.layer_primitive_nodes(0)
{ {
egui::Color32::from_rgb(255, 100, 100) let shape = primitive
} else { .primitive(autorouter.router().layout().drawing())
egui::Color32::from_rgb(200, 52, 52) .shape();
};
painter.paint_shape(&shape, color);
}
for zone in autorouter.router().layout().layer_zone_nodes(0) { let color = if overlay
let color = if overlay.selection().contains(&GenericNode::Compound(zone)) { .selection()
egui::Color32::from_rgb(255, 100, 100) .contains(&GenericNode::Primitive(primitive))
} else { {
egui::Color32::from_rgb(200, 52, 52) egui::Color32::from_rgb(255, 100, 100)
}; } else {
painter.paint_polygon( egui::Color32::from_rgb(200, 52, 52)
&autorouter.router().layout().zone(zone).shape().polygon, };
color, painter.paint_shape(&shape, color);
) }
}
for edge in overlay.ratsnest().graph().edge_references() { for zone in autorouter.router().layout().layer_zone_nodes(0) {
let from = overlay let color =
.ratsnest() if overlay.selection().contains(&GenericNode::Compound(zone)) {
.graph() egui::Color32::from_rgb(255, 100, 100)
.node_weight(edge.source()) } else {
.unwrap() egui::Color32::from_rgb(200, 52, 52)
.pos; };
let to = overlay painter.paint_polygon(
.ratsnest() &autorouter.router().layout().zone(zone).shape().polygon,
.graph() color,
.node_weight(edge.target()) )
.unwrap() }
.pos;
painter.paint_edge(from, to, egui::Color32::from_rgb(90, 90, 200)); for edge in overlay.ratsnest().graph().edge_references() {
let from = overlay
.ratsnest()
.graph()
.node_weight(edge.source())
.unwrap()
.pos;
let to = overlay
.ratsnest()
.graph()
.node_weight(edge.target())
.unwrap()
.pos;
painter.paint_edge(from, to, egui::Color32::from_rgb(90, 90, 200));
}
} }
//unreachable!();
} }
}) })
}); });