game/debug/
path_counter.rs1use crate::ID;
2use abstutil::Counter;
3use map_gui::tools::ColorNetwork;
4use map_model::{IntersectionID, PathStep, RoadID, Traversable};
5use widgetry::mapspace::ToggleZoomed;
6use widgetry::tools::ColorLegend;
7use widgetry::{
8 Color, EventCtx, GfxCtx, HorizontalAlignment, Line, Outcome, Panel, State, Text,
9 VerticalAlignment, Widget,
10};
11
12use crate::app::App;
13use crate::app::Transition;
14use crate::common::CommonState;
15
16pub struct PathCounter {
18 panel: Panel,
19 draw: ToggleZoomed,
20 cnt: Counter<RoadID>,
21 tooltip: Option<Text>,
22}
23
24impl PathCounter {
25 pub fn demand_across_intersection(
26 ctx: &mut EventCtx,
27 app: &App,
28 i: IntersectionID,
29 ) -> Box<dyn State<App>> {
30 let map = &app.primary.map;
31 let sim = &app.primary.sim;
32 let mut cnt = Counter::new();
33 for agent in sim.active_agents() {
35 if let Some(path) = sim.get_path(agent) {
36 if path.get_steps().iter().any(|step| match step {
37 PathStep::Turn(t) | PathStep::ContraflowTurn(t) => t.parent == i,
38 _ => false,
39 }) {
40 for step in path.get_steps() {
42 if let Traversable::Lane(l) = step.as_traversable() {
43 cnt.inc(l.road);
44 }
45 }
46 }
47 }
48 }
49
50 let mut colorer = ColorNetwork::new(app);
51 colorer
53 .draw
54 .unzoomed
55 .push(Color::CYAN, map.get_i(i).polygon.clone());
56 colorer
57 .draw
58 .zoomed
59 .push(Color::CYAN.alpha(0.5), map.get_i(i).polygon.clone());
60
61 colorer.pct_roads(cnt.clone(), &app.cs.good_to_bad_red);
62
63 Box::new(PathCounter {
64 draw: colorer.build(ctx),
65 tooltip: None,
66 cnt,
67 panel: Panel::new_builder(Widget::col(vec![
68 Widget::row(vec![
69 Line(format!("Paths across {}", i))
70 .small_heading()
71 .into_widget(ctx),
72 ctx.style().btn_close_widget(ctx),
73 ]),
74 ColorLegend::gradient(
75 ctx,
76 &app.cs.good_to_bad_red,
77 vec!["lowest count", "highest"],
78 ),
79 ]))
80 .aligned(HorizontalAlignment::Center, VerticalAlignment::Top)
81 .build(ctx),
82 })
83 }
84}
85
86impl State<App> for PathCounter {
87 fn event(&mut self, ctx: &mut EventCtx, app: &mut App) -> Transition {
88 ctx.canvas_movement();
89 if ctx.redo_mouseover() {
90 app.primary.current_selection = app.mouseover_unzoomed_roads_and_intersections(ctx);
91 self.tooltip = None;
92 if let Some(r) = match app.primary.current_selection {
93 Some(ID::Lane(l)) => Some(l.road),
94 Some(ID::Road(r)) => Some(r),
95 _ => None,
96 } {
97 let n = self.cnt.get(r);
98 if n > 0 {
99 self.tooltip = Some(Text::from(abstutil::prettyprint_usize(n)));
100 }
101 } else {
102 app.primary.current_selection = None;
103 }
104 }
105
106 if let Outcome::Clicked(x) = self.panel.event(ctx) {
107 match x.as_ref() {
108 "close" => {
109 return Transition::Pop;
110 }
111 _ => unreachable!(),
112 }
113 }
114
115 Transition::Keep
116 }
117
118 fn draw(&self, g: &mut GfxCtx, app: &App) {
119 self.panel.draw(g);
120 CommonState::draw_osd(g, app);
121
122 self.draw.draw(g);
123
124 if let Some(ref txt) = self.tooltip {
125 g.draw_mouse_tooltip(txt.clone());
126 }
127 }
128}