feat(topola-egui): Display guide-bitangents on debug overlay

This commit is contained in:
Mikolaj Wielgus 2025-08-16 01:17:29 +02:00
parent 7fbfed710c
commit 5fd4926fb6
4 changed files with 78 additions and 34 deletions

View File

@ -167,6 +167,7 @@ pub struct ViewActions {
pub show_ratsnest: Switch, pub show_ratsnest: Switch,
pub show_navmesh: Switch, pub show_navmesh: Switch,
pub show_guide_circles: Switch, pub show_guide_circles: Switch,
pub show_guide_bitangents: Switch,
pub show_triangulation: Switch, pub show_triangulation: Switch,
pub show_triangulation_constraints: Switch, pub show_triangulation_constraints: Switch,
pub show_pathfinding_scores: Switch, pub show_pathfinding_scores: Switch,
@ -184,6 +185,10 @@ impl ViewActions {
show_navmesh: Action::new_keyless(tr.text("tr-menu-view-show-navmesh")).into_switch(), show_navmesh: Action::new_keyless(tr.text("tr-menu-view-show-navmesh")).into_switch(),
show_guide_circles: Action::new_keyless(tr.text("tr-menu-view-show-guide-circles")) show_guide_circles: Action::new_keyless(tr.text("tr-menu-view-show-guide-circles"))
.into_switch(), .into_switch(),
show_guide_bitangents: Action::new_keyless(
tr.text("tr-menu-view-show-guide-bitangents"),
)
.into_switch(),
show_triangulation: Action::new_keyless(tr.text("tr-menu-view-show-triangulation")) show_triangulation: Action::new_keyless(tr.text("tr-menu-view-show-triangulation"))
.into_switch(), .into_switch(),
show_triangulation_constraints: Action::new_keyless( show_triangulation_constraints: Action::new_keyless(
@ -224,6 +229,8 @@ impl ViewActions {
self.show_navmesh.checkbox(ui, &mut menu_bar.show_navmesh); self.show_navmesh.checkbox(ui, &mut menu_bar.show_navmesh);
self.show_guide_circles self.show_guide_circles
.checkbox(ui, &mut menu_bar.show_guide_circles); .checkbox(ui, &mut menu_bar.show_guide_circles);
self.show_guide_bitangents
.checkbox(ui, &mut menu_bar.show_guide_bitangents);
self.show_triangulation self.show_triangulation
.checkbox(ui, &mut menu_bar.show_triangulation); .checkbox(ui, &mut menu_bar.show_triangulation);
self.show_triangulation_constraints self.show_triangulation_constraints

View File

@ -4,12 +4,13 @@
use petgraph::{ use petgraph::{
data::DataMap, data::DataMap,
graph::NodeIndex,
visit::{EdgeRef, IntoEdgeReferences}, visit::{EdgeRef, IntoEdgeReferences},
}; };
use rstar::AABB; use rstar::AABB;
use topola::{ use topola::{
autorouter::invoker::GetDebugOverlayData, autorouter::invoker::GetDebugOverlayData,
board::AccessMesadata, board::{AccessMesadata, Board},
drawing::{ drawing::{
bend::BendIndex, bend::BendIndex,
dot::DotIndex, dot::DotIndex,
@ -21,9 +22,10 @@ use topola::{
graph::MakeRef, graph::MakeRef,
interactor::{activity::ActivityStepper, interaction::InteractionStepper}, interactor::{activity::ActivityStepper, interaction::InteractionStepper},
layout::poly::MakePolygon, layout::poly::MakePolygon,
math::{Circle, RotationSense}, math::{self, Circle, RotationSense},
router::{ router::{
navmesh::{BinavnodeNodeIndex, NavnodeIndex}, navcord::Navcord,
navmesh::{BinavnodeNodeIndex, Navmesh, NavnodeIndex},
ng::pie, ng::pie,
prenavmesh::PrenavmeshConstraint, prenavmesh::PrenavmeshConstraint,
}, },
@ -53,7 +55,7 @@ impl<'a> Displayer<'a> {
self.display_ratsnest(); self.display_ratsnest();
} }
if menu_bar.show_navmesh || menu_bar.show_guide_circles { if menu_bar.show_navmesh || menu_bar.show_guide_circles || menu_bar.show_guide_bitangents {
self.display_navmesh_or_guides(menu_bar); self.display_navmesh_or_guides(menu_bar);
} }
@ -227,6 +229,27 @@ impl<'a> Displayer<'a> {
self.painter.paint_line_segment(from, to, stroke); self.painter.paint_line_segment(from, to, stroke);
} }
if menu_bar.show_guide_bitangents {
if let Some(navcord) = activity.maybe_navcord() {
if let (Some(from_circle), Some(to_circle)) = (
Self::node_guide_circle(board, navmesh, navcord, edge.source().0),
Self::node_guide_circle(board, navmesh, navcord, edge.target().0),
) {
if let Ok(tangents) =
math::tangent_segments(from_circle, None, to_circle, None)
{
for tangent in tangents {
self.painter.paint_line_segment(
tangent.start_point(),
tangent.end_point(),
egui::Stroke::new(1.0, egui::Color32::WHITE),
)
}
}
}
}
}
if let Some(text) = activity.navedge_debug_text((edge.source(), edge.target())) if let Some(text) = activity.navedge_debug_text((edge.source(), edge.target()))
{ {
self.painter.paint_text( self.painter.paint_text(
@ -239,6 +262,20 @@ impl<'a> Displayer<'a> {
} }
for index in navmesh.graph().node_indices() { for index in navmesh.graph().node_indices() {
if menu_bar.show_guide_circles {
if let Some(navcord) = activity.maybe_navcord() {
if let Some(circle) =
Self::node_guide_circle(board, navmesh, navcord, index)
{
self.painter.paint_hollow_circle(
circle,
1.0,
egui::epaint::Color32::WHITE,
);
}
}
}
let navnode = NavnodeIndex(index); let navnode = NavnodeIndex(index);
let primitive = let primitive =
PrimitiveIndex::from(navmesh.node_weight(navnode).unwrap().node); PrimitiveIndex::from(navmesh.node_weight(navnode).unwrap().node);
@ -247,36 +284,6 @@ impl<'a> Displayer<'a> {
.shape() .shape()
.center(); .center();
if menu_bar.show_guide_circles {
if let Some(navcord) = activity.maybe_navcord() {
if let Ok(dot) = DotIndex::try_from(primitive) {
let drawing = board.layout().drawing();
self.painter.paint_hollow_circle(
drawing.dot_circle(
dot,
navcord.width,
drawing.conditions(navcord.head.face().into()).as_ref(),
),
1.0,
egui::epaint::Color32::WHITE,
);
} else if let Ok(bend) = BendIndex::try_from(primitive) {
let drawing = board.layout().drawing();
self.painter.paint_hollow_circle(
drawing.bend_circle(
bend,
navcord.width,
drawing.conditions(navcord.head.face().into()).as_ref(),
),
1.0,
egui::epaint::Color32::WHITE,
);
}
}
}
pos += match navmesh.node_weight(navnode).unwrap().maybe_sense { pos += match navmesh.node_weight(navnode).unwrap().maybe_sense {
Some(RotationSense::Counterclockwise) => [0.0, 150.0].into(), Some(RotationSense::Counterclockwise) => [0.0, 150.0].into(),
Some(RotationSense::Clockwise) => [-0.0, -150.0].into(), Some(RotationSense::Clockwise) => [-0.0, -150.0].into(),
@ -306,6 +313,33 @@ impl<'a> Displayer<'a> {
} }
} }
fn node_guide_circle(
board: &Board<impl AccessMesadata>,
navmesh: &Navmesh,
navcord: &Navcord,
index: NodeIndex<usize>,
) -> Option<Circle> {
let drawing = board.layout().drawing();
let navnode = NavnodeIndex(index);
let primitive = PrimitiveIndex::from(navmesh.node_weight(navnode).unwrap().node);
if let Ok(dot) = DotIndex::try_from(primitive) {
Some(drawing.dot_circle(
dot,
navcord.width,
drawing.conditions(navcord.head.face().into()).as_ref(),
))
} else if let Ok(bend) = BendIndex::try_from(primitive) {
Some(drawing.bend_circle(
bend,
navcord.width,
drawing.conditions(navcord.head.face().into()).as_ref(),
))
} else {
None
}
}
fn display_triangulation(&mut self) { fn display_triangulation(&mut self) {
let board = self.workspace.interactor.invoker().autorouter().board(); let board = self.workspace.interactor.invoker().autorouter().board();

View File

@ -30,6 +30,7 @@ pub struct MenuBar {
pub show_ratsnest: bool, pub show_ratsnest: bool,
pub show_navmesh: bool, pub show_navmesh: bool,
pub show_guide_circles: bool, pub show_guide_circles: bool,
pub show_guide_bitangents: bool,
pub show_triangulation: bool, pub show_triangulation: bool,
pub show_triangulation_constraints: bool, pub show_triangulation_constraints: bool,
pub show_pathfinding_scores: bool, pub show_pathfinding_scores: bool,
@ -56,6 +57,7 @@ impl MenuBar {
show_ratsnest: true, show_ratsnest: true,
show_navmesh: false, show_navmesh: false,
show_guide_circles: false, show_guide_circles: false,
show_guide_bitangents: false,
show_triangulation: false, show_triangulation: false,
show_triangulation_constraints: false, show_triangulation_constraints: false,
show_pathfinding_scores: false, show_pathfinding_scores: false,

View File

@ -23,6 +23,7 @@ tr-menu-view-zoom-to-fit = Zoom to Fit
tr-menu-view-show-ratsnest = Show Ratsnest tr-menu-view-show-ratsnest = Show Ratsnest
tr-menu-view-show-navmesh = Show Navmesh tr-menu-view-show-navmesh = Show Navmesh
tr-menu-view-show-guide-circles = Show Guide-Circles tr-menu-view-show-guide-circles = Show Guide-Circles
tr-menu-view-show-guide-bitangents = Show Guide-Bitangents
tr-menu-view-show-triangulation = Show Triangulation tr-menu-view-show-triangulation = Show Triangulation
tr-menu-view-show-triangulation-constraints = Show Triangulation Constraints tr-menu-view-show-triangulation-constraints = Show Triangulation Constraints
tr-menu-view-show-pathfinding-scores = Show Pathfinding Scores tr-menu-view-show-pathfinding-scores = Show Pathfinding Scores