mirror of https://codeberg.org/topola/topola.git
Make it possible to hide debug overlay elements
This commit is contained in:
parent
18316e1a8f
commit
1433c02d81
|
|
@ -47,6 +47,9 @@ tr-menu-debug-show-triangulation = Show Triangulation
|
|||
tr-menu-debug-show-triangulation-constraints = Show Triangulation Constraints
|
||||
tr-menu-debug-show-pathfinding-scores = Show Pathfinding Scores
|
||||
tr-menu-debug-show-topo-navmesh = Show Topological Navmesh
|
||||
tr-menu-debug-show-repulsions = Show Repulsions
|
||||
tr-menu-debug-show-attractions = Show Attractions
|
||||
tr-menu-debug-show-retentions = Show Retentions
|
||||
tr-menu-debug-show-bboxes = Show BBoxes
|
||||
tr-menu-debug-show-primitive-indices = Show Primitive Indices
|
||||
tr-menu-debug-show-bend-endpoint-tangents = Show Bend Endpoint Tangents
|
||||
|
|
|
|||
|
|
@ -101,6 +101,11 @@ impl RunActions {
|
|||
|
||||
pub struct DebugActions {
|
||||
pub fix_step_rate: Switch,
|
||||
pub show_repulsions: Switch,
|
||||
pub show_attractions: Switch,
|
||||
pub show_retentions: Switch,
|
||||
pub show_bboxes: Switch,
|
||||
pub show_navmeshes: Switch,
|
||||
}
|
||||
|
||||
impl DebugActions {
|
||||
|
|
@ -108,10 +113,27 @@ impl DebugActions {
|
|||
Self {
|
||||
fix_step_rate: Action::new_keyless(tr.text("tr-menu-debug-fix-step-rate"))
|
||||
.into_switch(),
|
||||
show_repulsions: Action::new_keyless(tr.text("tr-menu-debug-show-repulsions"))
|
||||
.into_switch(),
|
||||
show_attractions: Action::new_keyless(tr.text("tr-menu-debug-show-attractions"))
|
||||
.into_switch(),
|
||||
show_retentions: Action::new_keyless(tr.text("tr-menu-debug-show-retentions"))
|
||||
.into_switch(),
|
||||
show_bboxes: Action::new_keyless(tr.text("tr-menu-debug-show-bboxes")).into_switch(),
|
||||
show_navmeshes: Action::new_keyless(tr.text("tr-menu-debug-show-navmesh"))
|
||||
.into_switch(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render_menu(&mut self, _ctx: &Context, ui: &mut Ui, menu_bar: &mut MenuBar) {
|
||||
self.fix_step_rate.checkbox(ui, &mut menu_bar.fix_step_rate);
|
||||
|
||||
ui.separator();
|
||||
|
||||
self.show_repulsions.checkbox(ui, &mut menu_bar.show_repulsions);
|
||||
self.show_attractions.checkbox(ui, &mut menu_bar.show_attractions);
|
||||
self.show_retentions.checkbox(ui, &mut menu_bar.show_retentions);
|
||||
self.show_bboxes.checkbox(ui, &mut menu_bar.show_bboxes);
|
||||
self.show_navmeshes.checkbox(ui, &mut menu_bar.show_navmeshes);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,338 @@
|
|||
// SPDX-FileCopyrightText: 2026 Topola contributors
|
||||
//
|
||||
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||
|
||||
use crate::{controller::Controller, viewport::Viewport};
|
||||
use topola::{Orientation, Vector2, Workspace};
|
||||
|
||||
pub struct DebugOverlay {}
|
||||
|
||||
pub struct DebugOverlayOptions {
|
||||
pub repulsions: bool,
|
||||
pub attractions: bool,
|
||||
pub retentions: bool,
|
||||
pub bboxes: bool,
|
||||
pub navmeshes: bool,
|
||||
}
|
||||
|
||||
impl DebugOverlay {
|
||||
pub fn new() -> Self {
|
||||
Self {}
|
||||
}
|
||||
|
||||
pub fn update(
|
||||
&mut self,
|
||||
ctx: &egui::Context,
|
||||
ui: &egui::Ui,
|
||||
viewport: &Viewport,
|
||||
workspace: &Controller,
|
||||
options: &DebugOverlayOptions,
|
||||
) {
|
||||
if options.repulsions {
|
||||
self.display_repulsions(ui, viewport, workspace);
|
||||
}
|
||||
if options.attractions {
|
||||
self.display_attractions(ui, viewport, workspace);
|
||||
}
|
||||
if options.retentions {
|
||||
self.display_retentions(ui, viewport, workspace);
|
||||
}
|
||||
if options.bboxes {
|
||||
self.display_bboxes(ctx, ui, viewport, workspace);
|
||||
}
|
||||
if options.navmeshes {
|
||||
self.display_navmeshes(ctx, ui, viewport, workspace);
|
||||
}
|
||||
}
|
||||
|
||||
fn display_repulsions(&mut self, ui: &egui::Ui, viewport: &Viewport, workspace: &Controller) {
|
||||
crate::profile_function!();
|
||||
let board = workspace.workspace.board();
|
||||
let stroke = egui::Stroke::new(150.0 / viewport.scale_factor(), egui::Color32::YELLOW);
|
||||
|
||||
for selector in &workspace.workspace.selection().components.0 {
|
||||
let Some(component_id) = board.component_id(&selector.component) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let Some(bbox) = board.layout().component_bbox2(component_id) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let origin = Vector2::new((bbox.min.x + bbox.max.x) / 2, (bbox.min.y + bbox.max.y) / 2);
|
||||
|
||||
Self::paint_arrows(
|
||||
ui,
|
||||
origin,
|
||||
board
|
||||
.layout()
|
||||
.locate_component_repulsions(component_id, Orientation::Oblique),
|
||||
stroke,
|
||||
);
|
||||
}
|
||||
|
||||
for selector in &workspace.workspace.selection().pins.0 {
|
||||
let Some(pin_id) = board.pin_id(&selector.pin) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
Self::paint_arrows(
|
||||
ui,
|
||||
board.layout().pin_centroid(pin_id),
|
||||
board
|
||||
.layout()
|
||||
.locate_pin_repulsions(pin_id, Orientation::Oblique),
|
||||
stroke,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn display_retentions(&mut self, ui: &egui::Ui, viewport: &Viewport, workspace: &Controller) {
|
||||
crate::profile_function!();
|
||||
let board = workspace.workspace.board();
|
||||
let layout = board.layout();
|
||||
let stroke = egui::Stroke::new(
|
||||
150.0 / viewport.scale_factor(),
|
||||
egui::Color32::from_rgb(192, 64, 255),
|
||||
);
|
||||
|
||||
for selector in &workspace.workspace.selection().components.0 {
|
||||
let Some(component_id) = board.component_id(&selector.component) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let Some(bbox) = layout.component_bbox2(component_id) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let origin = Vector2::new((bbox.min.x + bbox.max.x) / 2, (bbox.min.y + bbox.max.y) / 2);
|
||||
|
||||
Self::paint_arrows(
|
||||
ui,
|
||||
origin,
|
||||
layout.component_retentions(component_id),
|
||||
stroke,
|
||||
);
|
||||
}
|
||||
|
||||
for selector in &workspace.workspace.selection().pins.0 {
|
||||
let Some(pin_id) = board.pin_id(&selector.pin) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
Self::paint_arrows(
|
||||
ui,
|
||||
layout.pin_centroid(pin_id),
|
||||
layout.pin_retentions(pin_id),
|
||||
stroke,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn display_attractions(&mut self, ui: &egui::Ui, viewport: &Viewport, workspace: &Controller) {
|
||||
crate::profile_function!();
|
||||
let board = workspace.workspace.board();
|
||||
let layout = board.layout();
|
||||
let stroke = egui::Stroke::new(150.0 / viewport.scale_factor(), egui::Color32::BLUE);
|
||||
|
||||
for selector in &workspace.workspace.selection().components.0 {
|
||||
let Some(component_id) = board.component_id(&selector.component) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let Some(bbox) = layout.component_bbox2(component_id) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let origin = Vector2::new((bbox.min.x + bbox.max.x) / 2, (bbox.min.y + bbox.max.y) / 2);
|
||||
|
||||
Self::paint_arrows(
|
||||
ui,
|
||||
origin,
|
||||
layout.component_attractions(component_id),
|
||||
stroke,
|
||||
);
|
||||
}
|
||||
|
||||
for selector in &workspace.workspace.selection().pins.0 {
|
||||
let Some(pin_id) = board.pin_id(&selector.pin) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
Self::paint_arrows(
|
||||
ui,
|
||||
layout.pin_centroid(pin_id),
|
||||
layout.pin_attractions(pin_id),
|
||||
stroke,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn paint_arrows(
|
||||
ui: &egui::Ui,
|
||||
origin: Vector2<i64>,
|
||||
repulsions: impl IntoIterator<Item = Vector2<i64>>,
|
||||
stroke: egui::Stroke,
|
||||
) {
|
||||
for repulsion in repulsions {
|
||||
if repulsion.x == 0 && repulsion.y == 0 {
|
||||
continue;
|
||||
}
|
||||
|
||||
ui.painter().arrow(
|
||||
egui::pos2(origin.x as f32, origin.y as f32),
|
||||
egui::vec2(repulsion.x as f32, repulsion.y as f32),
|
||||
stroke,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn display_bboxes(
|
||||
&mut self,
|
||||
ctx: &egui::Context,
|
||||
ui: &egui::Ui,
|
||||
viewport: &Viewport,
|
||||
workspace: &Controller,
|
||||
) {
|
||||
crate::profile_function!();
|
||||
let board = workspace.workspace.board();
|
||||
let layout = board.layout();
|
||||
|
||||
for layer in workspace
|
||||
.appearance_panel
|
||||
.layers_in_display_order(*layout.layer_count())
|
||||
{
|
||||
if !workspace.appearance_panel.visible[layer.index()] {
|
||||
continue;
|
||||
}
|
||||
|
||||
for joint_id in layout.layer_joints(layer) {
|
||||
let bbox = layout.joint(joint_id).bbox();
|
||||
ui.painter().rect_stroke(
|
||||
egui::Rect {
|
||||
min: egui::pos2(bbox.min.x as f32, bbox.min.y as f32),
|
||||
max: egui::pos2(bbox.max.x as f32, bbox.max.y as f32),
|
||||
},
|
||||
egui::CornerRadius::ZERO,
|
||||
egui::Stroke::new(5.0, egui::Color32::GRAY),
|
||||
egui::StrokeKind::Middle,
|
||||
);
|
||||
}
|
||||
|
||||
for segment_id in layout.layer_segments(layer) {
|
||||
let endpoints = layout.segment(segment_id).endpoints;
|
||||
|
||||
ui.painter().rect_stroke(
|
||||
egui::Rect::from_two_pos(
|
||||
egui::pos2(endpoints[0].x as f32, endpoints[0].y as f32),
|
||||
egui::pos2(endpoints[1].x as f32, endpoints[1].y as f32),
|
||||
),
|
||||
egui::CornerRadius::ZERO,
|
||||
egui::Stroke::new(5.0, egui::Color32::GRAY),
|
||||
egui::StrokeKind::Middle,
|
||||
);
|
||||
}
|
||||
|
||||
for via_id in layout.layer_vias(layer) {
|
||||
let via = layout.via(via_id);
|
||||
let bbox = via.bbox();
|
||||
|
||||
ui.painter().rect_stroke(
|
||||
egui::Rect {
|
||||
min: egui::pos2(bbox.min.x as f32, bbox.min.y as f32),
|
||||
max: egui::pos2(bbox.max.x as f32, bbox.max.y as f32),
|
||||
},
|
||||
egui::CornerRadius::ZERO,
|
||||
egui::Stroke::new(5.0, egui::Color32::GRAY),
|
||||
egui::StrokeKind::Middle,
|
||||
);
|
||||
}
|
||||
|
||||
for polygon_id in layout.layer_polygons(layer) {
|
||||
let polygon = layout.polygon(polygon_id);
|
||||
let bbox = polygon.bbox();
|
||||
|
||||
ui.painter().rect_stroke(
|
||||
egui::Rect {
|
||||
min: egui::pos2(bbox.min.x as f32, bbox.min.y as f32),
|
||||
max: egui::pos2(bbox.max.x as f32, bbox.max.y as f32),
|
||||
},
|
||||
egui::CornerRadius::ZERO,
|
||||
egui::Stroke::new(5.0, egui::Color32::GRAY),
|
||||
egui::StrokeKind::Middle,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn display_navmeshes(
|
||||
&mut self,
|
||||
ctx: &egui::Context,
|
||||
ui: &egui::Ui,
|
||||
viewport: &Viewport,
|
||||
workspace: &Controller,
|
||||
) {
|
||||
crate::profile_function!();
|
||||
let Workspace::Autorouter(autorouter_workspace) = &workspace.workspace else {
|
||||
return;
|
||||
};
|
||||
let autorouter = &autorouter_workspace.autorouter;
|
||||
|
||||
for layer in workspace
|
||||
.appearance_panel
|
||||
.layers_in_display_order(*workspace.workspace.board().layout().layer_count())
|
||||
{
|
||||
if workspace.appearance_panel.visible[layer.index()] {
|
||||
for navmesh in autorouter
|
||||
.router()
|
||||
.navmesher_board()
|
||||
.navmesher()
|
||||
.layer_navmeshers()[layer.index()]
|
||||
.navmeshes()
|
||||
{
|
||||
for edge_geom in navmesh
|
||||
.triangulation()
|
||||
.rtreed_dcel()
|
||||
.edges_rtree()
|
||||
.as_ref()
|
||||
.iter()
|
||||
{
|
||||
let (from_vertex, to_vertex) = navmesh
|
||||
.triangulation()
|
||||
.rtreed_dcel()
|
||||
.dcel()
|
||||
.edge_endpoints(edge_geom.data);
|
||||
let from = navmesh
|
||||
.triangulation()
|
||||
.rtreed_dcel()
|
||||
.dcel()
|
||||
.vertex_weight(from_vertex)
|
||||
.position();
|
||||
let to = navmesh
|
||||
.triangulation()
|
||||
.rtreed_dcel()
|
||||
.dcel()
|
||||
.vertex_weight(to_vertex)
|
||||
.position();
|
||||
ui.painter().line_segment(
|
||||
[
|
||||
egui::pos2(*from.x() as f32, *from.y() as f32),
|
||||
egui::pos2(*to.x() as f32, *to.y() as f32),
|
||||
],
|
||||
egui::Stroke::new(
|
||||
10.0,
|
||||
egui::Color32::WHITE,
|
||||
/*workspace
|
||||
.appearance_panel
|
||||
.colors(ctx)
|
||||
.layers
|
||||
.color(workspace.autorouter.navmesher_board().board().layer_name(layer))
|
||||
.normal,*/
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,9 +2,12 @@
|
|||
//
|
||||
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||
|
||||
use crate::{controller::Controller, viewport::Viewport};
|
||||
use crate::{
|
||||
controller::Controller, debug_overlay::{DebugOverlay, DebugOverlayOptions}, menu_bar::MenuBar,
|
||||
viewport::Viewport,
|
||||
};
|
||||
use topola::{
|
||||
Orientation, Vector2, Workspace,
|
||||
Workspace,
|
||||
layout::primitives::{Joint, Polygon, Segment, Via},
|
||||
};
|
||||
|
||||
|
|
@ -19,19 +22,29 @@ impl Display {
|
|||
&mut self,
|
||||
ctx: &egui::Context,
|
||||
ui: &egui::Ui,
|
||||
//menu_bar: &MenuBar,
|
||||
viewport: &Viewport,
|
||||
workspace: &Controller,
|
||||
menu_bar: &MenuBar,
|
||||
) {
|
||||
crate::profile_function!();
|
||||
|
||||
self.display_layout(ctx, ui, /*menu_bar,*/ viewport, workspace);
|
||||
self.display_repulsions(ui, viewport, workspace);
|
||||
self.display_attractions(ui, viewport, workspace);
|
||||
self.display_retentions(ui, viewport, workspace);
|
||||
self.display_bboxes(ctx, ui, viewport, workspace);
|
||||
self.display_navmeshes(ctx, ui, viewport, workspace);
|
||||
self.display_layout(ctx, ui, viewport, workspace);
|
||||
self.display_ratsnest(ctx, ui, viewport, workspace);
|
||||
|
||||
let mut debug_overlay = DebugOverlay::new();
|
||||
debug_overlay.update(
|
||||
ctx,
|
||||
ui,
|
||||
viewport,
|
||||
workspace,
|
||||
&DebugOverlayOptions {
|
||||
repulsions: menu_bar.show_repulsions,
|
||||
attractions: menu_bar.show_attractions,
|
||||
retentions: menu_bar.show_retentions,
|
||||
bboxes: menu_bar.show_bboxes,
|
||||
navmeshes: menu_bar.show_navmeshes,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
fn display_layout(
|
||||
|
|
@ -164,148 +177,6 @@ impl Display {
|
|||
);
|
||||
}
|
||||
|
||||
fn display_repulsions(&mut self, ui: &egui::Ui, viewport: &Viewport, workspace: &Controller) {
|
||||
crate::profile_function!();
|
||||
let board = workspace.workspace.board();
|
||||
let stroke = egui::Stroke::new(150.0 / viewport.scale_factor(), egui::Color32::YELLOW);
|
||||
|
||||
for selector in &workspace.workspace.selection().components.0 {
|
||||
let Some(component_id) = board.component_id(&selector.component) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let Some(bbox) = board.layout().component_bbox2(component_id) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let origin = Vector2::new((bbox.min.x + bbox.max.x) / 2, (bbox.min.y + bbox.max.y) / 2);
|
||||
|
||||
Self::paint_arrows(
|
||||
ui,
|
||||
origin,
|
||||
board
|
||||
.layout()
|
||||
.locate_component_repulsions(component_id, Orientation::Oblique),
|
||||
stroke,
|
||||
);
|
||||
}
|
||||
|
||||
for selector in &workspace.workspace.selection().pins.0 {
|
||||
let Some(pin_id) = board.pin_id(&selector.pin) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
Self::paint_arrows(
|
||||
ui,
|
||||
board.layout().pin_centroid(pin_id),
|
||||
board
|
||||
.layout()
|
||||
.locate_pin_repulsions(pin_id, Orientation::Oblique),
|
||||
stroke,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn display_retentions(&mut self, ui: &egui::Ui, viewport: &Viewport, workspace: &Controller) {
|
||||
crate::profile_function!();
|
||||
let board = workspace.workspace.board();
|
||||
let layout = board.layout();
|
||||
let stroke = egui::Stroke::new(
|
||||
150.0 / viewport.scale_factor(),
|
||||
egui::Color32::from_rgb(192, 64, 255),
|
||||
);
|
||||
|
||||
for selector in &workspace.workspace.selection().components.0 {
|
||||
let Some(component_id) = board.component_id(&selector.component) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let Some(bbox) = layout.component_bbox2(component_id) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let origin = Vector2::new((bbox.min.x + bbox.max.x) / 2, (bbox.min.y + bbox.max.y) / 2);
|
||||
|
||||
Self::paint_arrows(
|
||||
ui,
|
||||
origin,
|
||||
layout.component_retentions(component_id),
|
||||
stroke,
|
||||
);
|
||||
}
|
||||
|
||||
for selector in &workspace.workspace.selection().pins.0 {
|
||||
let Some(pin_id) = board.pin_id(&selector.pin) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
Self::paint_arrows(
|
||||
ui,
|
||||
layout.pin_centroid(pin_id),
|
||||
layout.pin_retentions(pin_id),
|
||||
stroke,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn display_attractions(&mut self, ui: &egui::Ui, viewport: &Viewport, workspace: &Controller) {
|
||||
crate::profile_function!();
|
||||
let board = workspace.workspace.board();
|
||||
let layout = board.layout();
|
||||
let stroke = egui::Stroke::new(150.0 / viewport.scale_factor(), egui::Color32::BLUE);
|
||||
|
||||
for selector in &workspace.workspace.selection().components.0 {
|
||||
let Some(component_id) = board.component_id(&selector.component) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let Some(bbox) = layout.component_bbox2(component_id) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let origin = Vector2::new((bbox.min.x + bbox.max.x) / 2, (bbox.min.y + bbox.max.y) / 2);
|
||||
|
||||
Self::paint_arrows(
|
||||
ui,
|
||||
origin,
|
||||
layout.component_attractions(component_id),
|
||||
stroke,
|
||||
);
|
||||
}
|
||||
|
||||
for selector in &workspace.workspace.selection().pins.0 {
|
||||
let Some(pin_id) = board.pin_id(&selector.pin) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
Self::paint_arrows(
|
||||
ui,
|
||||
layout.pin_centroid(pin_id),
|
||||
layout.pin_attractions(pin_id),
|
||||
stroke,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn paint_arrows(
|
||||
ui: &egui::Ui,
|
||||
origin: Vector2<i64>,
|
||||
repulsions: impl IntoIterator<Item = Vector2<i64>>,
|
||||
stroke: egui::Stroke,
|
||||
) {
|
||||
for repulsion in repulsions {
|
||||
if repulsion.x == 0 && repulsion.y == 0 {
|
||||
continue;
|
||||
}
|
||||
|
||||
ui.painter().arrow(
|
||||
egui::pos2(origin.x as f32, origin.y as f32),
|
||||
egui::vec2(repulsion.x as f32, repulsion.y as f32),
|
||||
stroke,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn paint_joint(
|
||||
&mut self,
|
||||
ctx: &egui::Context,
|
||||
|
|
@ -374,155 +245,6 @@ impl Display {
|
|||
));
|
||||
}
|
||||
|
||||
fn display_bboxes(
|
||||
&mut self,
|
||||
ctx: &egui::Context,
|
||||
ui: &egui::Ui,
|
||||
viewport: &Viewport,
|
||||
workspace: &Controller,
|
||||
) {
|
||||
crate::profile_function!();
|
||||
let board = workspace.workspace.board();
|
||||
let layout = board.layout();
|
||||
|
||||
for layer in workspace
|
||||
.appearance_panel
|
||||
.layers_in_display_order(*layout.layer_count())
|
||||
{
|
||||
if !workspace.appearance_panel.visible[layer.index()] {
|
||||
continue;
|
||||
}
|
||||
|
||||
for joint_id in layout.layer_joints(layer) {
|
||||
let bbox = layout.joint(joint_id).bbox();
|
||||
ui.painter().rect_stroke(
|
||||
egui::Rect {
|
||||
min: egui::pos2(bbox.min.x as f32, bbox.min.y as f32),
|
||||
max: egui::pos2(bbox.max.x as f32, bbox.max.y as f32),
|
||||
},
|
||||
egui::CornerRadius::ZERO,
|
||||
egui::Stroke::new(5.0, egui::Color32::GRAY),
|
||||
egui::StrokeKind::Middle,
|
||||
);
|
||||
}
|
||||
|
||||
for segment_id in layout.layer_segments(layer) {
|
||||
let endpoints = layout.segment(segment_id).endpoints;
|
||||
|
||||
ui.painter().rect_stroke(
|
||||
egui::Rect::from_two_pos(
|
||||
egui::pos2(endpoints[0].x as f32, endpoints[0].y as f32),
|
||||
egui::pos2(endpoints[1].x as f32, endpoints[1].y as f32),
|
||||
),
|
||||
egui::CornerRadius::ZERO,
|
||||
egui::Stroke::new(5.0, egui::Color32::GRAY),
|
||||
egui::StrokeKind::Middle,
|
||||
);
|
||||
}
|
||||
|
||||
for via_id in layout.layer_vias(layer) {
|
||||
let via = layout.via(via_id);
|
||||
let bbox = via.bbox();
|
||||
|
||||
ui.painter().rect_stroke(
|
||||
egui::Rect {
|
||||
min: egui::pos2(bbox.min.x as f32, bbox.min.y as f32),
|
||||
max: egui::pos2(bbox.max.x as f32, bbox.max.y as f32),
|
||||
},
|
||||
egui::CornerRadius::ZERO,
|
||||
egui::Stroke::new(5.0, egui::Color32::GRAY),
|
||||
egui::StrokeKind::Middle,
|
||||
);
|
||||
}
|
||||
|
||||
for polygon_id in layout.layer_polygons(layer) {
|
||||
let polygon = layout.polygon(polygon_id);
|
||||
let bbox = polygon.bbox();
|
||||
|
||||
ui.painter().rect_stroke(
|
||||
egui::Rect {
|
||||
min: egui::pos2(bbox.min.x as f32, bbox.min.y as f32),
|
||||
max: egui::pos2(bbox.max.x as f32, bbox.max.y as f32),
|
||||
},
|
||||
egui::CornerRadius::ZERO,
|
||||
egui::Stroke::new(5.0, egui::Color32::GRAY),
|
||||
egui::StrokeKind::Middle,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn display_navmeshes(
|
||||
&mut self,
|
||||
ctx: &egui::Context,
|
||||
ui: &egui::Ui,
|
||||
viewport: &Viewport,
|
||||
workspace: &Controller,
|
||||
) {
|
||||
crate::profile_function!();
|
||||
let Workspace::Autorouter(autorouter_workspace) = &workspace.workspace else {
|
||||
return;
|
||||
};
|
||||
let autorouter = &autorouter_workspace.autorouter;
|
||||
|
||||
for layer in workspace
|
||||
.appearance_panel
|
||||
.layers_in_display_order(*workspace.workspace.board().layout().layer_count())
|
||||
{
|
||||
if workspace.appearance_panel.visible[layer.index()] {
|
||||
for navmesh in autorouter
|
||||
.router()
|
||||
.navmesher_board()
|
||||
.navmesher()
|
||||
.layer_navmeshers()[layer.index()]
|
||||
.navmeshes()
|
||||
{
|
||||
for edge_geom in navmesh
|
||||
.triangulation()
|
||||
.rtreed_dcel()
|
||||
.edges_rtree()
|
||||
.as_ref()
|
||||
.iter()
|
||||
{
|
||||
let (from_vertex, to_vertex) = navmesh
|
||||
.triangulation()
|
||||
.rtreed_dcel()
|
||||
.dcel()
|
||||
.edge_endpoints(edge_geom.data);
|
||||
let from = navmesh
|
||||
.triangulation()
|
||||
.rtreed_dcel()
|
||||
.dcel()
|
||||
.vertex_weight(from_vertex)
|
||||
.position();
|
||||
let to = navmesh
|
||||
.triangulation()
|
||||
.rtreed_dcel()
|
||||
.dcel()
|
||||
.vertex_weight(to_vertex)
|
||||
.position();
|
||||
ui.painter().line_segment(
|
||||
[
|
||||
egui::pos2(*from.x() as f32, *from.y() as f32),
|
||||
egui::pos2(*to.x() as f32, *to.y() as f32),
|
||||
],
|
||||
egui::Stroke::new(
|
||||
10.0,
|
||||
egui::Color32::WHITE,
|
||||
/*workspace
|
||||
.appearance_panel
|
||||
.colors(ctx)
|
||||
.layers
|
||||
.color(workspace.autorouter.navmesher_board().board().layer_name(layer))
|
||||
.normal,*/
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn display_ratsnest(
|
||||
&mut self,
|
||||
_ctx: &egui::Context,
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ mod action;
|
|||
mod actions;
|
||||
mod app;
|
||||
mod controller;
|
||||
mod debug_overlay;
|
||||
mod display;
|
||||
mod layers_panel;
|
||||
mod menu_bar;
|
||||
|
|
|
|||
|
|
@ -29,6 +29,16 @@ pub struct MenuBar {
|
|||
pub step_rate: f64,
|
||||
#[serde(default)]
|
||||
pub show_profiler: bool,
|
||||
#[serde(default)]
|
||||
pub show_repulsions: bool,
|
||||
#[serde(default)]
|
||||
pub show_attractions: bool,
|
||||
#[serde(default)]
|
||||
pub show_retentions: bool,
|
||||
#[serde(default)]
|
||||
pub show_bboxes: bool,
|
||||
#[serde(default)]
|
||||
pub show_navmeshes: bool,
|
||||
}
|
||||
|
||||
impl MenuBar {
|
||||
|
|
@ -37,6 +47,11 @@ impl MenuBar {
|
|||
fix_step_rate: false,
|
||||
step_rate: 1.0,
|
||||
show_profiler: false,
|
||||
show_repulsions: false,
|
||||
show_attractions: false,
|
||||
show_retentions: false,
|
||||
show_bboxes: false,
|
||||
show_navmeshes: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ impl Viewport {
|
|||
.show(ui, &mut scene_rect, |ui| {
|
||||
if let Some(ref controller) = controller {
|
||||
let mut display = Display::new();
|
||||
display.update(ctx, ui, &self, controller);
|
||||
display.update(ctx, ui, &self, controller, menu_bar);
|
||||
}
|
||||
})
|
||||
.response;
|
||||
|
|
|
|||
Loading…
Reference in New Issue