Remove the GetDrawAgents indirection. Originally the UI could pull the

set of agents to draw either from the simulation or from this
"time-traveler" plugin, which would let you rewind sim time. That plugin
is long gone, and it never worked well, because much of the UI would use
the GetDrawAgents to select something, then query the live sim for lots
of details anyway. The plugin never served all of those calls, so the
results would be kind of out-of-sync anyway.

There are some parts of the UI that need to temporarily not draw agents.
Use the same suspended_sim trick that edit mode does.
This commit is contained in:
Dustin Carlino 2020-10-12 11:52:05 -05:00
parent 4d549f80df
commit 1906fb0913
21 changed files with 125 additions and 263 deletions

View File

@ -7,7 +7,7 @@ use rand::seq::SliceRandom;
use abstutil::Timer;
use geom::{Bounds, Circle, Distance, Duration, Pt2D, Time};
use map_model::{IntersectionID, Map, Traversable};
use sim::{Analytics, DontDrawAgents, GetDrawAgents, Sim, SimCallback, SimFlags};
use sim::{Analytics, Sim, SimCallback, SimFlags};
use widgetry::{EventCtx, GfxCtx, Prerender};
use crate::challenges::HighScore;
@ -138,13 +138,7 @@ impl App {
)
}
pub fn draw(
&self,
g: &mut GfxCtx,
opts: DrawOptions,
source: &dyn GetDrawAgents,
show_objs: &dyn ShowObject,
) {
pub fn draw(&self, g: &mut GfxCtx, opts: DrawOptions, show_objs: &dyn ShowObject) {
let mut sample_intersection: Option<String> = None;
g.clear(self.cs.void_background);
@ -198,21 +192,13 @@ impl App {
}
let mut cache = self.primary.draw_map.agents.borrow_mut();
cache.draw_unzoomed_agents(
g,
source,
&self.primary.map,
&self.unzoomed_agents,
self.opts.debug_all_agents,
&self.cs,
);
cache.draw_unzoomed_agents(g, self);
} else {
let mut cache = self.primary.draw_map.agents.borrow_mut();
let objects = self.get_renderables_back_to_front(
g.get_screen_bounds(),
&g.prerender,
&mut cache,
source,
show_objs,
);
@ -259,54 +245,26 @@ impl App {
/// Assumes some defaults.
pub fn recalculate_current_selection(&mut self, ctx: &EventCtx) {
self.primary.current_selection = self.calculate_current_selection(
ctx,
&self.primary.sim,
&ShowEverything::new(),
false,
false,
false,
);
self.primary.current_selection =
self.calculate_current_selection(ctx, &ShowEverything::new(), false, false, false);
}
pub fn mouseover_unzoomed_roads_and_intersections(&self, ctx: &EventCtx) -> Option<ID> {
self.calculate_current_selection(
ctx,
&DontDrawAgents {},
&ShowEverything::new(),
false,
true,
false,
)
self.calculate_current_selection(ctx, &ShowEverything::new(), false, true, false)
}
pub fn mouseover_unzoomed_buildings(&self, ctx: &EventCtx) -> Option<ID> {
self.calculate_current_selection(
ctx,
&DontDrawAgents {},
&ShowEverything::new(),
false,
false,
true,
)
self.calculate_current_selection(ctx, &ShowEverything::new(), false, false, true)
}
pub fn mouseover_unzoomed_everything(&self, ctx: &EventCtx) -> Option<ID> {
self.calculate_current_selection(
ctx,
&DontDrawAgents {},
&ShowEverything::new(),
false,
true,
true,
)
self.calculate_current_selection(ctx, &ShowEverything::new(), false, true, true)
}
pub fn mouseover_debug_mode(&self, ctx: &EventCtx, show_objs: &dyn ShowObject) -> Option<ID> {
self.calculate_current_selection(ctx, &self.primary.sim, show_objs, true, false, false)
self.calculate_current_selection(ctx, show_objs, true, false, false)
}
fn calculate_current_selection(
&self,
ctx: &EventCtx,
source: &dyn GetDrawAgents,
show_objs: &dyn ShowObject,
debug_mode: bool,
unzoomed_roads_and_intersections: bool,
@ -326,7 +284,6 @@ impl App {
Circle::new(pt, Distance::meters(3.0)).get_bounds(),
ctx.prerender,
&mut cache,
source,
show_objs,
);
objects.reverse();
@ -377,7 +334,6 @@ impl App {
bounds: Bounds,
prerender: &Prerender,
agents: &'a mut AgentCache,
source: &dyn GetDrawAgents,
show_objs: &dyn ShowObject,
) -> Vec<&'a (dyn Renderable + 'a)> {
let map = &self.primary.map;
@ -442,7 +398,7 @@ impl App {
// Expand all of the Traversables into agents, populating the cache if needed.
{
for on in &agents_on {
agents.populate_if_needed(*on, map, source, &self.cs, prerender);
agents.populate_if_needed(*on, map, &self.primary.sim, &self.cs, prerender);
}
}

View File

@ -284,14 +284,7 @@ impl Minimap {
}
let mut cache = app.primary.draw_map.agents.borrow_mut();
cache.draw_unzoomed_agents(
g,
&app.primary.sim,
&app.primary.map,
&app.unzoomed_agents,
app.opts.debug_all_agents,
&app.cs,
);
cache.draw_unzoomed_agents(g, app);
// The cursor
let (x1, y1) = {

View File

@ -337,7 +337,7 @@ impl State for DebugMode {
fn draw(&self, g: &mut GfxCtx, app: &App) {
let mut opts = DrawOptions::new();
opts.label_buildings = self.layers.show_labels;
app.draw(g, opts, &app.primary.sim, self);
app.draw(g, opts, self);
if let Some(ref results) = self.search_results {
g.redraw(&results.draw);

View File

@ -1,7 +1,6 @@
use serde::{Deserialize, Serialize};
use geom::{Distance, LonLat, PolyLine, Polygon, Pt2D, Ring};
use sim::DontDrawAgents;
use widgetry::{
lctrl, Btn, Choice, Color, Drawable, EventCtx, GeomBatch, GfxCtx, HorizontalAlignment, Key,
Line, Outcome, Panel, RewriteColor, Text, VerticalAlignment, Widget,
@ -272,7 +271,7 @@ impl State for StoryMapEditor {
fn draw(&self, g: &mut GfxCtx, app: &App) {
let mut opts = DrawOptions::new();
opts.label_buildings = true;
app.draw(g, opts, &DontDrawAgents {}, &ShowEverything::new());
app.draw(g, opts, &ShowEverything::new());
match self.mode {
Mode::PlacingMarker => {

View File

@ -72,7 +72,7 @@ impl State for ClusterTrafficSignalEditor {
let mut opts = DrawOptions::new();
opts.suppress_traffic_signal_details
.extend(self.members.clone());
app.draw(g, opts, &app.primary.sim, &ShowEverything::new());
app.draw(g, opts, &ShowEverything::new());
}
let mut batch = GeomBatch::new();

View File

@ -454,7 +454,7 @@ impl State for TrafficSignalEditor {
let mut opts = DrawOptions::new();
opts.suppress_traffic_signal_details
.extend(self.members.clone());
app.draw(g, opts, &app.primary.sim, &ShowEverything::new());
app.draw(g, opts, &ShowEverything::new());
}
g.redraw(&self.fade_irrelevant);
g.redraw(&self.draw_current);

View File

@ -150,23 +150,13 @@ impl GUI for Game {
match state.draw_baselayer() {
DrawBaselayer::DefaultMap => {
self.app.draw(
g,
DrawOptions::new(),
&self.app.primary.sim,
&ShowEverything::new(),
);
self.app.draw(g, DrawOptions::new(), &ShowEverything::new());
}
DrawBaselayer::Custom => {}
DrawBaselayer::PreviousState => {
match self.states[self.states.len() - 2].draw_baselayer() {
DrawBaselayer::DefaultMap => {
self.app.draw(
g,
DrawOptions::new(),
&self.app.primary.sim,
&ShowEverything::new(),
);
self.app.draw(g, DrawOptions::new(), &ShowEverything::new());
}
DrawBaselayer::Custom => {}
// Nope, don't recurse

View File

@ -2,7 +2,7 @@ use std::collections::HashSet;
use abstutil::prettyprint_usize;
use geom::{Circle, Distance, Pt2D, Time};
use sim::{GetDrawAgents, PersonState};
use sim::PersonState;
use widgetry::{
Btn, Checkbox, Choice, Color, Drawable, EventCtx, GeomBatch, GfxCtx, HorizontalAlignment, Key,
Line, Outcome, Panel, Text, TextExt, VerticalAlignment, Widget,

View File

@ -6,7 +6,7 @@ use map_model::{
BuildingID, Map, OffstreetParking, ParkingLotID, PathConstraints, PathRequest, RoadID,
NORMAL_LANE_THICKNESS,
};
use sim::{GetDrawAgents, ParkingSpot, Scenario, VehicleType};
use sim::{ParkingSpot, Scenario, VehicleType};
use widgetry::{
Btn, Checkbox, Drawable, EventCtx, GeomBatch, GfxCtx, HorizontalAlignment, Key, Line, Outcome,
Panel, Text, TextExt, VerticalAlignment, Widget,

View File

@ -2,7 +2,7 @@ use std::collections::HashSet;
use abstutil::prettyprint_usize;
use geom::{Circle, Distance, Pt2D, Time};
use sim::{GetDrawAgents, PersonState};
use sim::PersonState;
use widgetry::{
Btn, Checkbox, Color, Drawable, EventCtx, GeomBatch, GfxCtx, HorizontalAlignment, Key, Line,
Outcome, Panel, VerticalAlignment, Widget,

View File

@ -5,7 +5,6 @@ use maplit::btreeset;
use abstutil::{prettyprint_usize, Counter};
use geom::{Circle, Distance, Duration, Polygon, Pt2D, Time};
use map_model::{IntersectionID, Map, Traversable, NORMAL_LANE_THICKNESS, SIDEWALK_THICKNESS};
use sim::GetDrawAgents;
use widgetry::{
Btn, Checkbox, Color, Drawable, EventCtx, GeomBatch, GfxCtx, HorizontalAlignment, Key, Line,
Outcome, Panel, Text, TextExt, VerticalAlignment, Widget,

View File

@ -10,7 +10,7 @@ use map_model::{
AreaID, BuildingID, BusStopID, IntersectionID, LaneID, Map, ParkingLotID, RoadID, Traversable,
NORMAL_LANE_THICKNESS, SIDEWALK_THICKNESS,
};
use sim::{GetDrawAgents, UnzoomedAgent, VehicleType};
use sim::{Sim, UnzoomedAgent, VehicleType};
use widgetry::{Color, Drawable, EventCtx, GeomBatch, GfxCtx, Prerender};
use crate::app::App;
@ -374,21 +374,21 @@ impl AgentCache {
&mut self,
on: Traversable,
map: &Map,
source: &dyn GetDrawAgents,
sim: &Sim,
cs: &ColorScheme,
prerender: &Prerender,
) {
let now = source.time();
let now = sim.time();
if Some(now) == self.time && self.agents_per_on.contains_key(&on) {
return;
}
let step_count = source.step_count();
let step_count = sim.step_count();
let mut list: Vec<Box<dyn Renderable>> = Vec::new();
for c in source.get_draw_cars(on, map).into_iter() {
for c in sim.get_draw_cars(on, map).into_iter() {
list.push(draw_vehicle(c, map, prerender, cs));
}
let (loners, crowds) = source.get_draw_peds(on, map);
let (loners, crowds) = sim.get_draw_peds(on, map);
for p in loners {
list.push(Box::new(DrawPedestrian::new(
p, step_count, map, prerender, cs,
@ -406,20 +406,10 @@ impl AgentCache {
self.agents_per_on.insert(on, list);
}
// TODO GetDrawAgents indirection added for time traveling, but that's been removed. Maybe
// simplify this.
pub fn draw_unzoomed_agents(
&mut self,
g: &mut GfxCtx,
source: &dyn GetDrawAgents,
map: &Map,
color_agents: &UnzoomedAgents,
debug_all_agents: bool,
cs: &ColorScheme,
) {
let now = source.time();
pub fn draw_unzoomed_agents(&mut self, g: &mut GfxCtx, app: &App) {
let now = app.primary.sim.time();
if let Some((time, ref orig_agents, ref draw)) = self.unzoomed {
if now == time && color_agents == orig_agents {
if now == time && app.unzoomed_agents == orig_agents.clone() {
g.redraw(draw);
return;
}
@ -432,8 +422,8 @@ impl AgentCache {
// don't leak out of the road too much.
let car_circle = Circle::new(Pt2D::new(0.0, 0.0), 4.0 * NORMAL_LANE_THICKNESS).to_polygon();
let ped_circle = Circle::new(Pt2D::new(0.0, 0.0), 4.0 * SIDEWALK_THICKNESS).to_polygon();
for agent in source.get_unzoomed_agents(map) {
if let Some(color) = color_agents.color(&agent) {
for agent in app.primary.sim.get_unzoomed_agents(&app.primary.map) {
if let Some(color) = app.unzoomed_agents.color(&agent) {
if agent.vehicle_type.is_some() {
batch.push(color, car_circle.translate(agent.pos.x(), agent.pos.y()));
} else {
@ -444,17 +434,17 @@ impl AgentCache {
let draw = g.upload(batch);
g.redraw(&draw);
self.unzoomed = Some((now, color_agents.clone(), draw));
self.unzoomed = Some((now, app.unzoomed_agents.clone(), draw));
if debug_all_agents {
if app.opts.debug_all_agents {
let mut cnt = 0;
for input in source.get_all_draw_cars(map) {
for input in app.primary.sim.get_all_draw_cars(&app.primary.map) {
cnt += 1;
draw_vehicle(input, map, g.prerender, cs);
draw_vehicle(input, &app.primary.map, g.prerender, &app.cs);
}
println!(
"At {}, debugged {} cars",
source.time(),
app.primary.sim.time(),
abstutil::prettyprint_usize(cnt)
);
// Pedestrians aren't the ones crashing

View File

@ -5,7 +5,7 @@ use maplit::hashset;
use abstutil::{prettyprint_usize, Counter, MultiMap};
use geom::{Distance, PolyLine, Polygon, Time};
use map_model::{osm, BuildingID, BuildingType, IntersectionID, LaneID, Map, RoadID, TurnType};
use sim::{DontDrawAgents, TripEndpoint, TripInfo, TripMode};
use sim::{TripEndpoint, TripInfo, TripMode};
use widgetry::{
AreaSlider, Btn, Checkbox, Color, Drawable, EventCtx, GeomBatch, GfxCtx, HorizontalAlignment,
Key, Line, Outcome, Panel, RewriteColor, Text, TextExt, VerticalAlignment, Widget,
@ -71,7 +71,10 @@ struct Filter {
type BlockID = usize;
impl CommuterPatterns {
pub fn new(ctx: &mut EventCtx, app: &App) -> Box<dyn State> {
pub fn new(ctx: &mut EventCtx, app: &mut App) -> Box<dyn State> {
assert!(app.primary.suspended_sim.is_none());
app.primary.suspended_sim = Some(app.primary.clear_sim());
let (bldg_to_block, border_to_block, blocks) =
ctx.loading_screen("group buildings into blocks", |_, _| group_bldgs(app));
@ -345,6 +348,7 @@ impl State for CommuterPatterns {
match self.panel.event(ctx) {
Outcome::Clicked(x) => match x.as_ref() {
"close" => {
app.primary.sim = app.primary.suspended_sim.take().unwrap();
return Transition::Pop;
}
_ => unreachable!(),
@ -442,12 +446,7 @@ impl State for CommuterPatterns {
}
fn draw(&self, g: &mut GfxCtx, app: &App) {
app.draw(
g,
DrawOptions::new(),
&DontDrawAgents {},
&ShowEverything::new(),
);
app.draw(g, DrawOptions::new(), &ShowEverything::new());
g.redraw(&self.draw_all_blocks);
g.redraw(&self.current_block.1);

View File

@ -3,7 +3,7 @@ use std::collections::HashMap;
use abstutil::{prettyprint_usize, Counter, Parallelism, Timer};
use geom::{ArrowCap, Distance, Duration, Polygon, Time};
use map_model::{ControlTrafficSignal, IntersectionID, MovementID, PathStep, TurnType};
use sim::{DontDrawAgents, TripEndpoint};
use sim::TripEndpoint;
use widgetry::{
Btn, Color, Drawable, EventCtx, GeomBatch, GfxCtx, HorizontalAlignment, Key, Line, Outcome,
Panel, Spinner, Text, TextExt, VerticalAlignment, Widget,
@ -26,6 +26,8 @@ pub struct TrafficSignalDemand {
impl TrafficSignalDemand {
pub fn new(ctx: &mut EventCtx, app: &mut App) -> Box<dyn State> {
app.primary.current_selection = None;
assert!(app.primary.suspended_sim.is_none());
app.primary.suspended_sim = Some(app.primary.clear_sim());
let all_demand = ctx.loading_screen("predict all demand", |_, timer| {
Demand::all_demand(app, timer)
@ -100,6 +102,7 @@ impl State for TrafficSignalDemand {
match self.panel.event(ctx) {
Outcome::Clicked(x) => match x.as_ref() {
"close" => {
app.primary.sim = app.primary.suspended_sim.take().unwrap();
return Transition::Pop;
}
_ => unreachable!(),
@ -133,7 +136,7 @@ impl State for TrafficSignalDemand {
let mut opts = DrawOptions::new();
opts.suppress_traffic_signal_details
.extend(self.all_demand.keys().cloned());
app.draw(g, opts, &DontDrawAgents {}, &ShowEverything::new());
app.draw(g, opts, &ShowEverything::new());
g.redraw(&self.draw_all);
if let Some((ref draw, ref count)) = self.selected {

View File

@ -1,6 +1,6 @@
use geom::{ArrowCap, Distance, Time};
use map_model::{LaneID, TurnType};
use sim::{AgentID, DontDrawAgents};
use sim::AgentID;
use widgetry::{
Btn, Color, Drawable, EventCtx, GeomBatch, GfxCtx, HorizontalAlignment, Key, Line, Outcome,
Panel, Text, TextExt, VerticalAlignment, Widget,
@ -116,7 +116,7 @@ impl State for TurnExplorer {
opts.suppress_traffic_signal_details.push(l.src_i);
opts.suppress_traffic_signal_details.push(l.dst_i);
}
app.draw(g, opts, &DontDrawAgents {}, &ShowEverything::new());
app.draw(g, opts, &ShowEverything::new());
if self.idx == 0 {
for turn in &app.primary.map.get_turns_from_lane(self.l) {

View File

@ -395,12 +395,7 @@ impl State for TimeWarpScreen {
if app.opts.dont_draw_time_warp {
g.clear(app.cs.section_bg);
} else {
app.draw(
g,
DrawOptions::new(),
&app.primary.sim,
&ShowEverything::new(),
);
app.draw(g, DrawOptions::new(), &ShowEverything::new());
State::grey_out_map(g, app);
}

View File

@ -2,7 +2,6 @@ use std::collections::BTreeSet;
use geom::ArrowCap;
use map_model::{IntersectionCluster, IntersectionID, PathConstraints};
use sim::DontDrawAgents;
use widgetry::{
Btn, Checkbox, Color, Drawable, EventCtx, GeomBatch, GfxCtx, HorizontalAlignment, Key, Line,
Outcome, Panel, Text, TextExt, VerticalAlignment, Widget,
@ -271,7 +270,7 @@ impl State for UberTurnViewer {
let mut opts = DrawOptions::new();
opts.suppress_traffic_signal_details
.extend(self.ic.members.clone());
app.draw(g, opts, &DontDrawAgents {}, &ShowEverything::new());
app.draw(g, opts, &ShowEverything::new());
self.panel.draw(g);
g.redraw(&self.draw);

View File

@ -20,8 +20,8 @@ use map_model::{
};
pub use crate::render::{
CarStatus, DontDrawAgents, DrawCarInput, DrawPedCrowdInput, DrawPedestrianInput, GetDrawAgents,
PedCrowdLocation, UnzoomedAgent,
CarStatus, DrawCarInput, DrawPedCrowdInput, DrawPedestrianInput, PedCrowdLocation,
UnzoomedAgent,
};
pub use self::analytics::{Analytics, TripPhase};

View File

@ -1,7 +1,7 @@
//! Intermediate structures so that sim and game crates don't have a cyclic dependency.
use geom::{Angle, Distance, PolyLine, Pt2D, Time};
use map_model::{BuildingID, Map, ParkingLotID, Traversable, TurnID};
use geom::{Angle, Distance, PolyLine, Pt2D};
use map_model::{BuildingID, ParkingLotID, Traversable, TurnID};
use crate::{CarID, PedestrianID, PersonID, VehicleType};
@ -63,59 +63,3 @@ pub struct UnzoomedAgent {
/// this is important enough to call out here.
pub parking: bool,
}
// TODO Can we return borrows instead? Nice for time travel, not for main sim?
// actually good for main sim too; we're constantly calculating stuff while sim is paused
// otherwise? except we don't know what to calculate. maybe cache it?
pub trait GetDrawAgents {
fn time(&self) -> Time;
/// Every time the time changes, this should increase. For smoothly animating stuff.
fn step_count(&self) -> usize;
fn get_draw_car(&self, id: CarID, map: &Map) -> Option<DrawCarInput>;
fn get_draw_ped(&self, id: PedestrianID, map: &Map) -> Option<DrawPedestrianInput>;
fn get_draw_cars(&self, on: Traversable, map: &Map) -> Vec<DrawCarInput>;
fn get_draw_peds(
&self,
on: Traversable,
map: &Map,
) -> (Vec<DrawPedestrianInput>, Vec<DrawPedCrowdInput>);
fn get_all_draw_cars(&self, map: &Map) -> Vec<DrawCarInput>;
fn get_all_draw_peds(&self, map: &Map) -> Vec<DrawPedestrianInput>;
fn get_unzoomed_agents(&self, map: &Map) -> Vec<UnzoomedAgent>;
}
pub struct DontDrawAgents;
impl GetDrawAgents for DontDrawAgents {
fn time(&self) -> Time {
Time::START_OF_DAY
}
fn step_count(&self) -> usize {
0
}
fn get_draw_car(&self, _: CarID, _: &Map) -> Option<DrawCarInput> {
None
}
fn get_draw_ped(&self, _: PedestrianID, _: &Map) -> Option<DrawPedestrianInput> {
None
}
fn get_draw_cars(&self, _: Traversable, _: &Map) -> Vec<DrawCarInput> {
Vec::new()
}
fn get_draw_peds(
&self,
_: Traversable,
_: &Map,
) -> (Vec<DrawPedestrianInput>, Vec<DrawPedCrowdInput>) {
(Vec::new(), Vec::new())
}
fn get_all_draw_cars(&self, _: &Map) -> Vec<DrawCarInput> {
Vec::new()
}
fn get_all_draw_peds(&self, _: &Map) -> Vec<DrawPedestrianInput> {
Vec::new()
}
fn get_unzoomed_agents(&self, _: &Map) -> Vec<UnzoomedAgent> {
Vec::new()
}
}

View File

@ -17,13 +17,11 @@ use map_model::{
pub use self::queries::AgentProperties;
use crate::{
AgentID, AlertLocation, Analytics, CapSimState, CarID, Command, CreateCar, DrawCarInput,
DrawPedCrowdInput, DrawPedestrianInput, DrivingSimState, Event, GetDrawAgents,
IntersectionSimState, OrigPersonID, PandemicModel, ParkedCar, ParkingSim, ParkingSimState,
ParkingSpot, PedestrianID, Person, PersonID, Router, Scheduler, SidewalkPOI, SidewalkSpot,
TransitSimState, TripID, TripManager, TripPhaseType, TripSpawner, UnzoomedAgent, Vehicle,
VehicleSpec, VehicleType, WalkingSimState, BUS_LENGTH, LIGHT_RAIL_LENGTH, MIN_CAR_LENGTH,
SPAWN_DIST,
AgentID, AlertLocation, Analytics, CapSimState, CarID, Command, CreateCar, DrivingSimState,
Event, IntersectionSimState, OrigPersonID, PandemicModel, ParkedCar, ParkingSim,
ParkingSimState, ParkingSpot, Person, PersonID, Router, Scheduler, SidewalkPOI, SidewalkSpot,
TransitSimState, TripID, TripManager, TripPhaseType, TripSpawner, Vehicle, VehicleSpec,
VehicleType, WalkingSimState, BUS_LENGTH, LIGHT_RAIL_LENGTH, MIN_CAR_LENGTH, SPAWN_DIST,
};
mod queries;
@ -365,69 +363,6 @@ impl Sim {
}
}
// Drawing
impl GetDrawAgents for Sim {
fn time(&self) -> Time {
self.time
}
fn step_count(&self) -> usize {
self.step_count
}
fn get_draw_car(&self, id: CarID, map: &Map) -> Option<DrawCarInput> {
self.parking.get_draw_car(id, map).or_else(|| {
self.driving
.get_single_draw_car(id, self.time, map, &self.transit)
})
}
fn get_draw_ped(&self, id: PedestrianID, map: &Map) -> Option<DrawPedestrianInput> {
self.walking.get_draw_ped(id, self.time, map)
}
fn get_draw_cars(&self, on: Traversable, map: &Map) -> Vec<DrawCarInput> {
let mut results = Vec::new();
if let Traversable::Lane(l) = on {
if map.get_l(l).is_parking() {
return self.parking.get_draw_cars(l, map);
}
results.extend(self.parking.get_draw_cars_in_lots(l, map));
}
results.extend(
self.driving
.get_draw_cars_on(self.time, on, map, &self.transit),
);
results
}
fn get_draw_peds(
&self,
on: Traversable,
map: &Map,
) -> (Vec<DrawPedestrianInput>, Vec<DrawPedCrowdInput>) {
self.walking.get_draw_peds_on(self.time, on, map)
}
fn get_all_draw_cars(&self, map: &Map) -> Vec<DrawCarInput> {
let mut result = self
.driving
.get_all_draw_cars(self.time, map, &self.transit);
result.extend(self.parking.get_all_draw_cars(map));
result
}
fn get_all_draw_peds(&self, map: &Map) -> Vec<DrawPedestrianInput> {
self.walking.get_all_draw_peds(self.time, map)
}
fn get_unzoomed_agents(&self, map: &Map) -> Vec<UnzoomedAgent> {
let mut result = self.driving.get_unzoomed_agents(self.time, map);
result.extend(self.walking.get_unzoomed_agents(self.time, map));
result
}
}
// Running
impl Sim {
// Advances time as minimally as possible, also limited by max_dt. Returns true if the callback

View File

@ -5,14 +5,15 @@ use std::collections::{BTreeMap, HashSet};
use abstutil::Counter;
use geom::{Distance, Duration, PolyLine, Pt2D, Time};
use map_model::{
BuildingID, BusRouteID, BusStopID, IntersectionID, Lane, LaneID, Map, Path, Position, TurnID,
BuildingID, BusRouteID, BusStopID, IntersectionID, Lane, LaneID, Map, Path, Position,
Traversable, TurnID,
};
use crate::analytics::Window;
use crate::{
AgentID, AgentType, Analytics, CarID, GetDrawAgents, OrigPersonID, PandemicModel, ParkedCar,
ParkingSim, PedestrianID, Person, PersonID, PersonState, Scenario, Sim, TripID, TripInfo,
TripResult, VehicleType,
AgentID, AgentType, Analytics, CarID, DrawCarInput, DrawPedCrowdInput, DrawPedestrianInput,
OrigPersonID, PandemicModel, ParkedCar, ParkingSim, PedestrianID, Person, PersonID,
PersonState, Scenario, Sim, TripID, TripInfo, TripResult, UnzoomedAgent, VehicleType,
};
// TODO Many of these just delegate to an inner piece. This is unorganized and hard to maintain.
@ -380,6 +381,65 @@ impl Sim {
}
}
// Drawing
impl Sim {
pub fn step_count(&self) -> usize {
self.step_count
}
pub fn get_draw_car(&self, id: CarID, map: &Map) -> Option<DrawCarInput> {
self.parking.get_draw_car(id, map).or_else(|| {
self.driving
.get_single_draw_car(id, self.time, map, &self.transit)
})
}
pub fn get_draw_ped(&self, id: PedestrianID, map: &Map) -> Option<DrawPedestrianInput> {
self.walking.get_draw_ped(id, self.time, map)
}
pub fn get_draw_cars(&self, on: Traversable, map: &Map) -> Vec<DrawCarInput> {
let mut results = Vec::new();
if let Traversable::Lane(l) = on {
if map.get_l(l).is_parking() {
return self.parking.get_draw_cars(l, map);
}
results.extend(self.parking.get_draw_cars_in_lots(l, map));
}
results.extend(
self.driving
.get_draw_cars_on(self.time, on, map, &self.transit),
);
results
}
pub fn get_draw_peds(
&self,
on: Traversable,
map: &Map,
) -> (Vec<DrawPedestrianInput>, Vec<DrawPedCrowdInput>) {
self.walking.get_draw_peds_on(self.time, on, map)
}
pub fn get_all_draw_cars(&self, map: &Map) -> Vec<DrawCarInput> {
let mut result = self
.driving
.get_all_draw_cars(self.time, map, &self.transit);
result.extend(self.parking.get_all_draw_cars(map));
result
}
pub fn get_all_draw_peds(&self, map: &Map) -> Vec<DrawPedestrianInput> {
self.walking.get_all_draw_peds(self.time, map)
}
pub fn get_unzoomed_agents(&self, map: &Map) -> Vec<UnzoomedAgent> {
let mut result = self.driving.get_unzoomed_agents(self.time, map);
result.extend(self.walking.get_unzoomed_agents(self.time, map));
result
}
}
pub struct AgentProperties {
// TODO Of this leg of the trip only!
pub total_time: Duration,