feat(topola-egui): Hide ratlines that were already routed

This commit is contained in:
Mikolaj Wielgus 2025-09-22 15:03:14 +02:00
parent 00aa79ff31
commit d74a06b2ea
4 changed files with 35 additions and 32 deletions

View File

@ -162,8 +162,18 @@ impl<'a> Displayer<'a> {
} }
fn display_ratsnest(&mut self) { fn display_ratsnest(&mut self) {
let graph = self.workspace.overlay.ratsnest().graph(); let graph = self
.workspace
.interactor
.invoker()
.autorouter()
.ratsnest()
.graph();
for edge in graph.edge_references() { for edge in graph.edge_references() {
if edge.weight().band_termseg.is_some() {
continue;
}
let from = graph.node_weight(edge.source()).unwrap().pos; let from = graph.node_weight(edge.source()).unwrap().pos;
let to = graph.node_weight(edge.target()).unwrap().pos; let to = graph.node_weight(edge.target()).unwrap().pos;

View File

@ -279,20 +279,20 @@ impl MenuBar {
// NOTE: we need to check `unselect` first because `Ctrl+A` would also match `Ctrl+Shift+A` // NOTE: we need to check `unselect` first because `Ctrl+A` would also match `Ctrl+Shift+A`
workspace.overlay.unselect_all(); workspace.overlay.unselect_all();
} else if actions.edit.select_all.consume_key_triggered(ctx, ui) { } else if actions.edit.select_all.consume_key_triggered(ctx, ui) {
let board = workspace.interactor.invoker().autorouter().board(); workspace.overlay.select_all(
workspace workspace.interactor.invoker().autorouter(),
.overlay &workspace.appearance_panel,
.select_all(board, &workspace.appearance_panel); );
} else if actions } else if actions
.edit .edit
.recalculate_topo_navmesh .recalculate_topo_navmesh
.consume_key_triggered(ctx, ui) .consume_key_triggered(ctx, ui)
{ {
if let Some(active_layer) = workspace.appearance_panel.active_layer { if let Some(active_layer) = workspace.appearance_panel.active_layer {
let board = workspace.interactor.invoker().autorouter().board(); workspace.overlay.recalculate_topo_navmesh(
workspace workspace.interactor.invoker().autorouter(),
.overlay active_layer,
.recalculate_topo_navmesh(board, active_layer); );
} }
} else if actions.place.place_via.consume_key_enabled( } else if actions.place.place_via.consume_key_enabled(
ctx, ctx,

View File

@ -8,8 +8,8 @@ use spade::InsertionError;
use topola::{ use topola::{
autorouter::{ autorouter::{
ratsnest::Ratsnest,
selection::{BboxSelectionKind, Selection}, selection::{BboxSelectionKind, Selection},
Autorouter,
}, },
board::{AccessMesadata, Board}, board::{AccessMesadata, Board},
router::ng::{calculate_navmesh as ng_calculate_navmesh, PieNavmesh}, router::ng::{calculate_navmesh as ng_calculate_navmesh, PieNavmesh},
@ -25,7 +25,6 @@ pub enum SelectionMode {
} }
pub struct Overlay { pub struct Overlay {
ratsnest: Ratsnest,
pub selection: Selection, pub selection: Selection,
planar_incr_navmesh: Option<PieNavmesh>, planar_incr_navmesh: Option<PieNavmesh>,
reselect_bbox: Option<(SelectionMode, Point)>, reselect_bbox: Option<(SelectionMode, Point)>,
@ -36,7 +35,6 @@ const INF: f64 = f64::INFINITY;
impl Overlay { impl Overlay {
pub fn new(board: &Board<impl AccessMesadata>) -> Result<Self, InsertionError> { pub fn new(board: &Board<impl AccessMesadata>) -> Result<Self, InsertionError> {
Ok(Self { Ok(Self {
ratsnest: Ratsnest::new(board.layout())?,
selection: Selection::new(), selection: Selection::new(),
planar_incr_navmesh: None, planar_incr_navmesh: None,
reselect_bbox: None, reselect_bbox: None,
@ -49,11 +47,11 @@ impl Overlay {
pub fn select_all( pub fn select_all(
&mut self, &mut self,
board: &Board<impl AccessMesadata>, autorouter: &Autorouter<impl AccessMesadata>,
appearance_panel: &AppearancePanel, appearance_panel: &AppearancePanel,
) { ) {
self.select_all_in_bbox( self.select_all_in_bbox(
board, autorouter.board(),
appearance_panel, appearance_panel,
&AABB::from_corners([-INF, -INF], [INF, INF]), &AABB::from_corners([-INF, -INF], [INF, INF]),
BboxSelectionKind::CompletelyInside, BboxSelectionKind::CompletelyInside,
@ -67,17 +65,17 @@ impl Overlay {
pub fn recalculate_topo_navmesh( pub fn recalculate_topo_navmesh(
&mut self, &mut self,
board: &Board<impl AccessMesadata>, autorouter: &Autorouter<impl AccessMesadata>,
active_layer: usize, active_layer: usize,
) { ) {
if let Ok(pien) = ng_calculate_navmesh(board, active_layer) { if let Ok(pien) = ng_calculate_navmesh(autorouter.board(), active_layer) {
self.planar_incr_navmesh = Some(pien); self.planar_incr_navmesh = Some(pien);
} }
} }
pub fn drag_start( pub fn drag_start(
&mut self, &mut self,
_board: &Board<impl AccessMesadata>, _autorouter: &Autorouter<impl AccessMesadata>,
_appearance_panel: &AppearancePanel, _appearance_panel: &AppearancePanel,
at: Point, at: Point,
ctrl: bool, ctrl: bool,
@ -98,7 +96,7 @@ impl Overlay {
pub fn drag_stop( pub fn drag_stop(
&mut self, &mut self,
board: &Board<impl AccessMesadata>, autorouter: &Autorouter<impl AccessMesadata>,
appearance_panel: &AppearancePanel, appearance_panel: &AppearancePanel,
at: Point, at: Point,
) { ) {
@ -109,14 +107,14 @@ impl Overlay {
match selmode { match selmode {
SelectionMode::Substitution => { SelectionMode::Substitution => {
self.selection = Selection::new(); self.selection = Selection::new();
self.select_all_in_bbox(board, appearance_panel, &aabb, bsk); self.select_all_in_bbox(autorouter.board(), appearance_panel, &aabb, bsk);
} }
SelectionMode::Addition => { SelectionMode::Addition => {
self.select_all_in_bbox(board, appearance_panel, &aabb, bsk); self.select_all_in_bbox(autorouter.board(), appearance_panel, &aabb, bsk);
} }
SelectionMode::Toggling => { SelectionMode::Toggling => {
let old_selection = self.take_selection(); let old_selection = self.take_selection();
self.select_all_in_bbox(board, appearance_panel, &aabb, bsk); self.select_all_in_bbox(autorouter.board(), appearance_panel, &aabb, bsk);
self.selection ^= &old_selection; self.selection ^= &old_selection;
} }
} }
@ -125,20 +123,20 @@ impl Overlay {
pub fn click( pub fn click(
&mut self, &mut self,
board: &Board<impl AccessMesadata>, autorouter: &Autorouter<impl AccessMesadata>,
appearance_panel: &AppearancePanel, appearance_panel: &AppearancePanel,
at: Point, at: Point,
) { ) {
if self.reselect_bbox.is_some() { if self.reselect_bbox.is_some() {
// handle bounding box selection (takes precendence over other interactions) // handle bounding box selection (takes precendence over other interactions)
// this is mostly in order to allow the user to recover from a missed/dropped drag_stop event // this is mostly in order to allow the user to recover from a missed/dropped drag_stop event
self.drag_stop(board, appearance_panel, at); self.drag_stop(autorouter, appearance_panel, at);
return; return;
} }
let old_selection = self.take_selection(); let old_selection = self.take_selection();
self.select_all_in_bbox( self.select_all_in_bbox(
board, autorouter.board(),
appearance_panel, appearance_panel,
&AABB::from_point([at.x(), at.y()]), &AABB::from_point([at.x(), at.y()]),
BboxSelectionKind::MerelyIntersects, BboxSelectionKind::MerelyIntersects,
@ -157,10 +155,6 @@ impl Overlay {
.select_all_in_bbox(board, aabb, &appearance_panel.visible[..], bsk); .select_all_in_bbox(board, aabb, &appearance_panel.visible[..], bsk);
} }
pub fn ratsnest(&self) -> &Ratsnest {
&self.ratsnest
}
pub fn selection(&self) -> &Selection { pub fn selection(&self) -> &Selection {
&self.selection &self.selection
} }

View File

@ -111,7 +111,6 @@ impl Workspace {
} }
} }
} else { } else {
let board = self.interactor.invoker().autorouter().board();
match interactive_event.kind { match interactive_event.kind {
InteractiveEventKind::PointerPrimaryButtonClicked => { InteractiveEventKind::PointerPrimaryButtonClicked => {
if menu_bar.is_placing_via { if menu_bar.is_placing_via {
@ -127,7 +126,7 @@ impl Workspace {
})); }));
} else { } else {
self.overlay.click( self.overlay.click(
board, self.interactor.invoker().autorouter(),
&self.appearance_panel, &self.appearance_panel,
interactive_input.pointer_pos, interactive_input.pointer_pos,
); );
@ -135,7 +134,7 @@ impl Workspace {
} }
InteractiveEventKind::PointerPrimaryButtonDragStarted => { InteractiveEventKind::PointerPrimaryButtonDragStarted => {
self.overlay.drag_start( self.overlay.drag_start(
board, self.interactor.invoker().autorouter(),
&self.appearance_panel, &self.appearance_panel,
interactive_input.pointer_pos, interactive_input.pointer_pos,
interactive_event.ctrl, interactive_event.ctrl,
@ -144,7 +143,7 @@ impl Workspace {
} }
InteractiveEventKind::PointerPrimaryButtonDragStopped => { InteractiveEventKind::PointerPrimaryButtonDragStopped => {
self.overlay.drag_stop( self.overlay.drag_stop(
board, self.interactor.invoker().autorouter(),
&self.appearance_panel, &self.appearance_panel,
interactive_input.pointer_pos, interactive_input.pointer_pos,
); );