game/debug/
objects.rs

1use crate::ID;
2use map_model::{Map, Position};
3use sim::{AgentID, Sim};
4use widgetry::{GfxCtx, Key, Text};
5
6use crate::app::App;
7
8pub struct ObjectDebugger;
9
10impl ObjectDebugger {
11    pub fn draw(&self, g: &mut GfxCtx, app: &App) {
12        if g.is_key_down(Key::LeftControl) {
13            if let Some(pt) = g.canvas.get_cursor_in_map_space() {
14                let mut txt = Text::new();
15                txt.add_line(pt.to_string());
16                txt.add_line(pt.to_gps(app.primary.map.get_gps_bounds()).to_string());
17                txt.add_line(format!("{:?}", g.canvas.get_cursor()));
18                txt.add_line(format!("zoom: {}", g.canvas.cam_zoom));
19                txt.add_line(format!(
20                    "cam_x = {}, cam_y = {}",
21                    g.canvas.cam_x, g.canvas.cam_y
22                ));
23                if let Some(ID::Lane(l)) = app.primary.current_selection {
24                    let lane = app.primary.map.get_l(l);
25                    let pl = &lane.lane_center_pts;
26                    if let Some((dist, _)) = pl.dist_along_of_point(pl.project_pt(pt)) {
27                        txt.add_line(Position::new(l, dist).to_string());
28                    }
29                    txt.add_line(format!(
30                        "{:?}",
31                        lane.get_nearest_side_of_road(&app.primary.map)
32                    ));
33                }
34                g.draw_mouse_tooltip(txt);
35            }
36        }
37    }
38
39    pub fn dump_debug(id: ID, map: &Map, sim: &Sim) {
40        match id {
41            ID::Lane(id) => {
42                let l = map.get_l(id);
43                println!("{}", abstutil::to_json(l));
44
45                sim.debug_lane(id);
46
47                let r = map.get_parent(id);
48                println!("Parent {} ({}) points to {}", r.id, r.orig_id, r.dst_i);
49                println!("{}", abstutil::to_json(r));
50            }
51            ID::Intersection(id) => {
52                let i = map.get_i(id);
53                println!("{}", abstutil::to_json(i));
54
55                println!("{}", sim.debug_intersection_json(id, map));
56
57                println!("{} connecting:", i.orig_id);
58                for r in &i.roads {
59                    let road = map.get_r(*r);
60                    println!("- {} = {}", road.id, road.orig_id);
61                }
62            }
63            ID::Building(id) => {
64                println!("{}", abstutil::to_json(map.get_b(id)));
65            }
66            ID::ParkingLot(id) => {
67                println!("{}", abstutil::to_json(map.get_pl(id)));
68            }
69            ID::Car(id) => {
70                sim.debug_car(id);
71                if let Some(t) = sim.agent_to_trip(AgentID::Car(id)) {
72                    println!("Trip log for {}", t);
73                    for p in sim.get_analytics().get_trip_phases(t, map) {
74                        println!("- {:?}", p);
75                    }
76                }
77            }
78            ID::Pedestrian(id) => {
79                sim.debug_ped(id);
80                if let Some(t) = sim.agent_to_trip(AgentID::Pedestrian(id)) {
81                    println!("Trip log for {}", t);
82                    for p in sim.get_analytics().get_trip_phases(t, map) {
83                        println!("- {:?}", p);
84                    }
85                }
86            }
87            ID::PedCrowd(members) => {
88                println!("Crowd with {} members", members.len());
89                for p in members {
90                    sim.debug_ped(p);
91                }
92            }
93            ID::TransitStop(id) => {
94                println!("{}", abstutil::to_json(map.get_ts(id)));
95            }
96            ID::Area(id) => {
97                println!("{}", abstutil::to_json(map.get_a(id)));
98            }
99            ID::Road(_) => unreachable!(),
100        }
101    }
102
103    pub fn debug_json(id: ID, map: &Map, sim: &Sim) {
104        let json_string = match id {
105            ID::Lane(id) => abstutil::to_json(map.get_l(id)),
106            ID::Intersection(id) => {
107                let json1 = abstutil::to_json(map.get_i(id));
108                let json2 = sim.debug_intersection_json(id, map);
109                format!("[{json1}, {json2}]")
110            }
111            ID::Building(id) => abstutil::to_json(map.get_b(id)),
112            ID::ParkingLot(id) => abstutil::to_json(map.get_pl(id)),
113            ID::Car(id) => sim.debug_agent_json(AgentID::Car(id)),
114            ID::Pedestrian(id) => sim.debug_agent_json(AgentID::Pedestrian(id)),
115            // Just show the first...
116            ID::PedCrowd(members) => sim.debug_agent_json(AgentID::Pedestrian(members[0])),
117            ID::TransitStop(id) => abstutil::to_json(map.get_ts(id)),
118            ID::Area(id) => abstutil::to_json(map.get_a(id)),
119            ID::Road(_) => unreachable!(),
120        };
121        #[cfg(target_arch = "wasm32")]
122        {
123            info!("{}", json_string);
124        }
125        #[cfg(not(target_arch = "wasm32"))]
126        {
127            use std::io::Write;
128
129            // The tempfile crate doesn't actually have a way to get the path... so just do this.
130            let path = format!("{}/abst_obj.json", std::env::temp_dir().display());
131            {
132                let mut f = fs_err::File::create(&path).unwrap();
133                writeln!(f, "{}", json_string).unwrap();
134            }
135            // Don't wait for the command to complete.
136            // Also, https://dadroit.com/ is the best viewer I've found so far, but we can change
137            // this to another or make it configurable with an environment variable or something
138            // once other people use this.
139            if let Err(err) = std::process::Command::new("dadroit").arg(path).spawn() {
140                warn!("Couldn't launch dadroit: {}", err);
141            }
142        }
143    }
144}