use info panel for finished trips

This commit is contained in:
Dustin Carlino 2020-01-17 10:53:09 -08:00
parent b6d7acd385
commit d5653e42ab
8 changed files with 43 additions and 157 deletions

View File

@ -98,14 +98,16 @@ impl InfoPanel {
_ => {}
}
let trip_details =
if let Some(trip) = id.agent_id().and_then(|a| ui.primary.sim.agent_to_trip(a)) {
let (rows, unzoomed, zoomed) = trip_details(trip, ctx, ui);
col.push(rows);
Some((unzoomed, zoomed))
} else {
None
};
let trip_details = if let Some(trip) = match id {
ID::Trip(t) => Some(t),
_ => id.agent_id().and_then(|a| ui.primary.sim.agent_to_trip(a)),
} {
let (rows, unzoomed, zoomed) = trip_details(trip, ctx, ui);
col.push(rows);
Some((unzoomed, zoomed))
} else {
None
};
// Follow the agent. When the sim is paused, this lets the player naturally pan away,
// because the InfoPanel isn't being updated.
@ -374,6 +376,8 @@ fn info_for(id: ID, ui: &UI) -> Text {
let a = map.get_a(id);
styled_kv(&mut txt, &a.osm_tags);
}
// No info here, trip_details will be used
ID::Trip(_) => {}
};
txt
}

View File

@ -4,14 +4,12 @@ mod minimap;
mod navigate;
mod panels;
mod shortcuts;
mod trip_explorer;
mod turn_cycler;
mod warp;
pub use self::colors::{ColorLegend, Colorer, ColorerBuilder};
pub use self::minimap::Minimap;
pub use self::panels::{edit_map_panel, tool_panel};
pub use self::trip_explorer::TripExplorer;
pub use self::warp::Warping;
use crate::game::Transition;
use crate::helpers::{list_names, ID};
@ -182,6 +180,9 @@ impl CommonState {
.collect();
list_names(&mut osd, |l| l.fg(name_color), routes);
}
ID::Trip(t) => {
osd.append(Line(t.to_string()).fg(id_color));
}
ID::ExtraShape(es) => {
// Only selectable in dev mode anyway
osd.append(Line(es.to_string()).fg(id_color));
@ -238,4 +239,10 @@ impl CommonState {
.suppress_traffic_signal_details(&ui.primary.map);
opts
}
// Meant to be used for launching from other states
pub fn launch_info_panel(&mut self, id: ID, ctx: &mut EventCtx, ui: &mut UI) {
self.info_panel = Some(info::InfoPanel::new(id, ctx, ui, Vec::new()));
ui.per_obj.info_panel_open = true;
}
}

View File

@ -1,134 +0,0 @@
use crate::common::ColorLegend;
use crate::game::{State, Transition};
use crate::helpers::rotating_color_map;
use crate::render::MIN_ZOOM_FOR_DETAIL;
use crate::ui::UI;
use ezgui::{hotkey, Drawable, EventCtx, GeomBatch, GfxCtx, Key, Line, ModalMenu, Text};
use geom::{Circle, Distance};
use sim::{TripEnd, TripID, TripStart};
pub struct TripExplorer {
menu: ModalMenu,
unzoomed: Drawable,
zoomed: Drawable,
legend: ColorLegend,
}
impl TripExplorer {
pub fn new(trip: TripID, ctx: &mut EventCtx, ui: &UI) -> TripExplorer {
let map = &ui.primary.map;
let phases = ui.primary.sim.get_analytics().get_trip_phases(trip, map);
// TODO Hack because ColorLegend only takes &str
let mut rows = Vec::new();
for (idx, p) in phases.iter().enumerate() {
rows.push((
p.describe(ui.primary.sim.time()),
rotating_color_map(idx + 1),
));
}
let mut unzoomed = GeomBatch::new();
let mut zoomed = GeomBatch::new();
for (p, (_, color)) in phases.iter().zip(rows.iter()) {
if let Some((dist, ref path)) = p.path {
if let Some(t) = path.trace(map, dist, None) {
unzoomed.push(*color, t.make_polygons(Distance::meters(10.0)));
zoomed.push(*color, t.make_polygons(Distance::meters(1.0)));
}
}
}
// Handle endpoints
let (trip_start, trip_end) = ui.primary.sim.trip_endpoints(trip);
let start_color = rotating_color_map(0);
match trip_start {
TripStart::Bldg(b) => {
let bldg = map.get_b(b);
rows.insert(0, (format!("start at {}", bldg.get_name(map)), start_color));
unzoomed.push(start_color, bldg.polygon.clone());
zoomed.push(start_color, bldg.polygon.clone());
}
TripStart::Border(i) => {
let i = map.get_i(i);
rows.insert(0, (format!("enter map via {}", i.id), start_color));
unzoomed.push(start_color, i.polygon.clone());
zoomed.push(start_color, i.polygon.clone());
}
};
// Is the trip ongoing?
if let Some(pt) = ui.primary.sim.get_canonical_pt_per_trip(trip, map).ok() {
let color = rotating_color_map(rows.len());
unzoomed.push(color, Circle::new(pt, Distance::meters(10.0)).to_polygon());
zoomed.push(
color.alpha(0.7),
Circle::new(pt, Distance::meters(5.0)).to_polygon(),
);
rows.push((format!("currently here"), color));
}
let end_color = rotating_color_map(rows.len());
match trip_end {
TripEnd::Bldg(b) => {
let bldg = map.get_b(b);
rows.push((format!("end at {}", bldg.get_name(map)), end_color));
unzoomed.push(end_color, bldg.polygon.clone());
zoomed.push(end_color, bldg.polygon.clone());
}
TripEnd::Border(i) => {
let i = map.get_i(i);
rows.push((format!("leave map via {}", i.id), end_color));
unzoomed.push(end_color, i.polygon.clone());
zoomed.push(end_color, i.polygon.clone());
}
// TODO TripExplorer is pretty useless for buses; maybe ShowBusRoute or something
// instead
TripEnd::ServeBusRoute(br) => {
rows.push((
format!("serve route {} forever", map.get_br(br).name),
end_color,
));
}
};
let legend = ColorLegend::new(
ctx,
Text::from(Line(&trip.to_string())),
rows.iter()
.map(|(label, color)| (label.as_str(), *color))
.collect(),
);
TripExplorer {
menu: ModalMenu::new(trip.to_string(), vec![(hotkey(Key::Escape), "quit")], ctx),
legend,
unzoomed: unzoomed.upload(ctx),
zoomed: zoomed.upload(ctx),
}
}
}
impl State for TripExplorer {
fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI) -> Transition {
if ctx.redo_mouseover() {
ui.recalculate_current_selection(ctx);
}
ctx.canvas_movement();
self.menu.event(ctx);
if self.menu.action("quit") {
return Transition::Pop;
}
Transition::Keep
}
fn draw(&self, g: &mut GfxCtx, _: &UI) {
if g.canvas.cam_zoom < MIN_ZOOM_FOR_DETAIL {
g.redraw(&self.unzoomed);
} else {
g.redraw(&self.zoomed);
}
self.legend.draw(g);
self.menu.draw(g);
}
}

View File

@ -55,9 +55,6 @@ impl ObjectDebugger {
fn dump_debug(id: ID, map: &Map, sim: &Sim, draw_map: &DrawMap) {
match id {
ID::Road(id) => {
println!("{}", abstutil::to_json(map.get_r(id)));
}
ID::Lane(id) => {
let l = map.get_l(id);
println!("{}", abstutil::to_json(l));
@ -155,5 +152,6 @@ fn dump_debug(id: ID, map: &Map, sim: &Sim, draw_map: &DrawMap) {
ID::Area(id) => {
println!("{}", abstutil::to_json(map.get_a(id)));
}
ID::Road(_) | ID::Trip(_) => unreachable!(),
}
}

View File

@ -5,11 +5,11 @@ use ezgui::{Color, Line, Text, TextSpan};
use geom::Pt2D;
use map_model::{AreaID, BuildingID, BusStopID, IntersectionID, LaneID, RoadID, TurnID};
use serde_derive::{Deserialize, Serialize};
use sim::{AgentID, CarID, PedestrianID};
use sim::{AgentID, CarID, PedestrianID, TripID};
use std::collections::{BTreeMap, BTreeSet, HashMap};
use std::fmt::Write;
// Aside from Road, everything here can actually be selected.
// Aside from Road and Trip, everything here can actually be selected.
#[derive(Clone, Hash, PartialEq, Eq, Debug, PartialOrd, Ord)]
pub enum ID {
Road(RoadID),
@ -23,6 +23,7 @@ pub enum ID {
ExtraShape(ExtraShapeID),
BusStop(BusStopID),
Area(AreaID),
Trip(TripID),
}
impl abstutil::Cloneable for ID {}
@ -70,6 +71,7 @@ impl ID {
.maybe_get_bs(id)
.map(|bs| bs.sidewalk_pos.pt(&primary.map)),
ID::Area(id) => primary.map.maybe_get_a(id).map(|a| a.polygon.center()),
ID::Trip(id) => primary.sim.get_canonical_pt_per_trip(id, &primary.map).ok(),
}
}
}

View File

@ -1,8 +1,8 @@
use crate::common::TripExplorer;
use crate::game::{State, Transition};
use crate::helpers::ID;
use crate::managed::{Callback, Composite, ManagedGUIState};
use crate::sandbox::bus_explorer;
use crate::sandbox::gameplay::{cmp_count_fewer, cmp_count_more, cmp_duration_shorter};
use crate::sandbox::{bus_explorer, SandboxMode};
use crate::ui::UI;
use abstutil::prettyprint_usize;
use abstutil::Counter;
@ -262,8 +262,14 @@ fn pick_finished_trips(
let trip = *id;
cbs.push((
label,
Box::new(move |ctx, ui| {
Some(Transition::Push(Box::new(TripExplorer::new(trip, ctx, ui))))
Box::new(move |_, _| {
Some(Transition::PopWithData(Box::new(move |state, ui, ctx| {
state
.downcast_mut::<SandboxMode>()
.unwrap()
.common
.launch_info_panel(ID::Trip(trip), ctx, ui);
})))
}),
));
}

View File

@ -31,7 +31,7 @@ pub struct SandboxMode {
agent_meter: AgentMeter,
overlay: Overlays,
gameplay: gameplay::GameplayRunner,
common: CommonState,
pub common: CommonState,
tool_panel: crate::managed::Composite,
minimap: Option<Minimap>,
}

View File

@ -323,9 +323,12 @@ impl UI {
ID::Building(id) => buildings.push(draw_map.get_b(id)),
ID::ExtraShape(id) => extra_shapes.push(draw_map.get_es(id)),
ID::BusStop(_) | ID::Turn(_) | ID::Car(_) | ID::Pedestrian(_) | ID::PedCrowd(_) => {
panic!("{:?} shouldn't be in the quadtree", id)
}
ID::BusStop(_)
| ID::Turn(_)
| ID::Car(_)
| ID::Pedestrian(_)
| ID::PedCrowd(_)
| ID::Trip(_) => panic!("{:?} shouldn't be in the quadtree", id),
}
}