egui: animate routing as it goes, show attempted traces

This commit is contained in:
Mikolaj Wielgus 2024-05-05 12:55:08 +02:00
parent a2c8ae7e70
commit b82f5417c3
2 changed files with 69 additions and 22 deletions

View File

@ -15,7 +15,7 @@ use topola::{
graph::{MakePrimitive, PrimitiveIndex}, graph::{MakePrimitive, PrimitiveIndex},
primitive::MakePrimitiveShape, primitive::MakePrimitiveShape,
rules::RulesTrait, rules::RulesTrait,
Drawing, Drawing, Infringement, LayoutException,
}, },
dsn::{design::DsnDesign, rules::DsnRules}, dsn::{design::DsnDesign, rules::DsnRules},
geometry::{ geometry::{
@ -35,6 +35,13 @@ use topola::{
use crate::{overlay::Overlay, painter::Painter}; use crate::{overlay::Overlay, painter::Painter};
#[derive(Debug, Default)]
struct SharedData {
pub path: Vec<VertexIndex>,
pub ghosts: Vec<PrimitiveShape>,
pub highlighteds: Vec<PrimitiveIndex>,
}
/// Deserialize/Serialize is needed to persist app state between restarts. /// Deserialize/Serialize is needed to persist app state between restarts.
#[derive(serde::Deserialize, serde::Serialize)] #[derive(serde::Deserialize, serde::Serialize)]
#[serde(default)] #[serde(default)]
@ -45,6 +52,9 @@ pub struct App {
#[serde(skip)] #[serde(skip)]
layout: Option<Arc<Mutex<Layout<DsnRules>>>>, layout: Option<Arc<Mutex<Layout<DsnRules>>>>,
#[serde(skip)]
shared_data: Arc<Mutex<SharedData>>,
#[serde(skip)] #[serde(skip)]
text_channel: (Sender<String>, Receiver<String>), text_channel: (Sender<String>, Receiver<String>),
@ -57,6 +67,7 @@ impl Default for App {
Self { Self {
overlay: None, overlay: None,
layout: None, layout: None,
shared_data: Default::default(),
text_channel: channel(), text_channel: channel(),
from_rect: egui::Rect::from_x_y_ranges(0.0..=1000000.0, 0.0..=500000.0), from_rect: egui::Rect::from_x_y_ranges(0.0..=1000000.0, 0.0..=500000.0),
} }
@ -75,23 +86,50 @@ impl App {
} }
} }
struct EmptyRouterObserver; struct DebugRouterObserver {
shared_data: Arc<Mutex<SharedData>>,
impl<R: RulesTrait + std::fmt::Debug> RouterObserverTrait<R> for EmptyRouterObserver {
fn on_rework(&mut self, _tracer: &Tracer<R>, _trace: &Trace) {
//dbg!(_tracer, _trace);
} }
fn before_probe(&mut self, _tracer: &Tracer<R>, _trace: &Trace, _edge: NavmeshEdgeReference) {
impl<R: RulesTrait + std::fmt::Debug> RouterObserverTrait<R> for DebugRouterObserver {
fn on_rework(&mut self, tracer: &Tracer<R>, trace: &Trace) {
//dbg!(_tracer, _trace);
let mut shared_data = self.shared_data.lock().unwrap();
shared_data.path = trace.path.clone();
shared_data.ghosts = vec![];
shared_data.highlighteds = vec![];
std::thread::sleep_ms(500);
}
fn before_probe(&mut self, tracer: &Tracer<R>, trace: &Trace, edge: NavmeshEdgeReference) {
//dbg!(_tracer, _trace, _edge); //dbg!(_tracer, _trace, _edge);
let mut shared_data = self.shared_data.lock().unwrap();
shared_data.path = trace.path.clone();
shared_data.path.push(edge.target());
shared_data.ghosts = vec![];
shared_data.highlighteds = vec![];
std::thread::sleep_ms(100);
} }
fn on_probe( fn on_probe(
&mut self, &mut self,
_tracer: &Tracer<R>, tracer: &Tracer<R>,
_trace: &Trace, trace: &Trace,
_edge: NavmeshEdgeReference, edge: NavmeshEdgeReference,
_result: Result<(), DrawException>, result: Result<(), DrawException>,
) { ) {
//dbg!(_tracer, _trace, _edge, _result); //dbg!(_tracer, _trace, _edge, _result);
let mut shared_data = self.shared_data.lock().unwrap();
let (ghosts, highlighteds, delay) = match result {
Err(DrawException::CannotWrapAround(
..,
LayoutException::Infringement(Infringement(shape1, infringee1)),
LayoutException::Infringement(Infringement(shape2, infringee2)),
)) => (vec![shape1, shape2], vec![infringee1, infringee2], 1500),
_ => (vec![], vec![], 300),
};
shared_data.path = trace.path.clone();
shared_data.ghosts = ghosts;
shared_data.highlighteds = highlighteds;
std::thread::sleep_ms(delay);
} }
fn on_estimate(&mut self, _tracer: &Tracer<R>, _vertex: VertexIndex) { fn on_estimate(&mut self, _tracer: &Tracer<R>, _vertex: VertexIndex) {
//dbg!(_tracer, _vertex); //dbg!(_tracer, _vertex);
@ -155,10 +193,11 @@ impl eframe::App for App {
if ui.button("Autoroute").clicked() { if ui.button("Autoroute").clicked() {
if let Some(layout_arc_mutex) = &self.layout { if let Some(layout_arc_mutex) = &self.layout {
let layout = layout_arc_mutex.clone(); let layout = layout_arc_mutex.clone();
let shared_data = self.shared_data.clone();
execute(async move { execute(async move {
let mut autorouter = Autorouter::new(layout).unwrap(); let mut autorouter = Autorouter::new(layout).unwrap();
autorouter.autoroute(&mut EmptyRouterObserver {}); autorouter.autoroute(&mut DebugRouterObserver { shared_data });
}); });
} }
} }
@ -201,9 +240,11 @@ impl eframe::App for App {
let mut painter = Painter::new(ui, transform); let mut painter = Painter::new(ui, transform);
if let Some(layout_arc_mutex) = &self.layout { if let Some(layout_arc_mutex) = &self.layout {
if let (layout, Some(overlay)) = if let (layout, shared_data, Some(overlay)) = (
(&layout_arc_mutex.lock().unwrap(), &mut self.overlay) &layout_arc_mutex.lock().unwrap(),
{ self.shared_data.lock().unwrap(),
&mut self.overlay,
) {
if ctx.input(|i| i.pointer.any_click()) { if ctx.input(|i| i.pointer.any_click()) {
overlay.click( overlay.click(
layout, layout,
@ -214,7 +255,8 @@ impl eframe::App for App {
for primitive in layout.drawing().layer_primitive_nodes(1) { for primitive in layout.drawing().layer_primitive_nodes(1) {
let shape = primitive.primitive(layout.drawing()).shape(); let shape = primitive.primitive(layout.drawing()).shape();
let color = if overlay let color = if shared_data.highlighteds.contains(&primitive)
|| overlay
.selection() .selection()
.contains(&GenericNode::Primitive(primitive)) .contains(&GenericNode::Primitive(primitive))
{ {
@ -238,7 +280,8 @@ impl eframe::App for App {
for primitive in layout.drawing().layer_primitive_nodes(0) { for primitive in layout.drawing().layer_primitive_nodes(0) {
let shape = primitive.primitive(layout.drawing()).shape(); let shape = primitive.primitive(layout.drawing()).shape();
let color = if overlay let color = if shared_data.highlighteds.contains(&primitive)
|| overlay
.selection() .selection()
.contains(&GenericNode::Primitive(primitive)) .contains(&GenericNode::Primitive(primitive))
{ {
@ -275,6 +318,10 @@ impl eframe::App for App {
painter.paint_edge(from, to, egui::Color32::from_rgb(90, 90, 200)); painter.paint_edge(from, to, egui::Color32::from_rgb(90, 90, 200));
} }
for ghost in shared_data.ghosts.iter() {
painter.paint_shape(&ghost, egui::Color32::from_rgb(75, 75, 150));
}
//unreachable!(); //unreachable!();
} }
} }

View File

@ -27,12 +27,12 @@ pub struct Trace {
#[derive(Debug)] #[derive(Debug)]
pub struct Tracer<'a, R: RulesTrait> { pub struct Tracer<'a, R: RulesTrait> {
pub layout: Arc<Mutex<Layout<R>>>, pub layout: Arc<Mutex<Layout<R>>>,
pub mesh: &'a Navmesh, pub navmesh: &'a Navmesh,
} }
impl<'a, R: RulesTrait> Tracer<'a, R> { impl<'a, R: RulesTrait> Tracer<'a, R> {
pub fn new(layout: Arc<Mutex<Layout<R>>>, mesh: &'a Navmesh) -> Self { pub fn new(layout: Arc<Mutex<Layout<R>>>, navmesh: &'a Navmesh) -> Self {
Tracer { layout, mesh } Tracer { layout, navmesh }
} }
pub fn start(&mut self, from: FixedDotIndex, width: f64) -> Trace { pub fn start(&mut self, from: FixedDotIndex, width: f64) -> Trace {