mirror of https://codeberg.org/topola/topola.git
egui: animate routing as it goes, show attempted traces
This commit is contained in:
parent
a2c8ae7e70
commit
b82f5417c3
|
|
@ -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 {
|
impl<R: RulesTrait + std::fmt::Debug> RouterObserverTrait<R> for DebugRouterObserver {
|
||||||
fn on_rework(&mut self, _tracer: &Tracer<R>, _trace: &Trace) {
|
fn on_rework(&mut self, tracer: &Tracer<R>, trace: &Trace) {
|
||||||
//dbg!(_tracer, _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) {
|
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!();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue