diff --git a/convert_osm/tests/determinism.rs b/convert_osm/tests/determinism.rs index 643d86242f..286ba9b480 100644 --- a/convert_osm/tests/determinism.rs +++ b/convert_osm/tests/determinism.rs @@ -8,6 +8,7 @@ fn convert_twice() { elevation: "../data/input/N47W122.hgt".to_string(), traffic_signals: "../data/input/TrafficSignals.shp".to_string(), parcels: "../data/seattle_parcels.abst".to_string(), + parking_shapes: "../data/shapes/blockface".to_string(), gtfs: "../data/input/google_transit_2018_18_08".to_string(), neighborhoods: "../data/input/neighborhoods.geojson".to_string(), output: "".to_string(), diff --git a/docs/design/time_travel.md b/docs/design/time_travel.md index 6d609a08e5..7ed06c89da 100644 --- a/docs/design/time_travel.md +++ b/docs/design/time_travel.md @@ -18,6 +18,8 @@ if each plugin should sort of declare a dependency on a live sim or if at a higher level, the list of plugins should change? Some initial steps: -- make a plugin that asks for all Draw stuff every tick and just saves it += make a plugin that asks for all Draw stuff every tick and just saves it - activate the time travel plugin and have keys to go back/forward +- supply the Draw{Car,Ped} stuff from the time travel plugin, not the sim - deactivate lots of other plugins while in this mode + - make sim ctrl a proper plugin diff --git a/editor/src/plugins/mod.rs b/editor/src/plugins/mod.rs index 66065ed9f9..6f89f74218 100644 --- a/editor/src/plugins/mod.rs +++ b/editor/src/plugins/mod.rs @@ -23,6 +23,7 @@ pub mod show_route; pub mod sim_controls; pub mod steep; pub mod stop_sign_editor; +pub mod time_travel; pub mod traffic_signal_editor; pub mod turn_cycler; pub mod warp; diff --git a/editor/src/plugins/time_travel.rs b/editor/src/plugins/time_travel.rs new file mode 100644 index 0000000000..f8c9535a87 --- /dev/null +++ b/editor/src/plugins/time_travel.rs @@ -0,0 +1,54 @@ +use plugins::{Plugin, PluginCtx}; +use map_model::Map; +use std::collections::BTreeMap; +use sim::{CarID, DrawCarInput, PedestrianID, DrawPedestrianInput, Sim, AgentID}; + +pub struct TimeTravel { + state_per_tick: Vec, +} + +struct StateAtTime { + cars: BTreeMap, + peds: BTreeMap, +} + +impl TimeTravel { + pub fn new() -> TimeTravel { + TimeTravel { + state_per_tick: Vec::new(), + } + } + + fn record_state(&mut self, sim: &Sim, map: &Map) { + // Record state for this tick, if needed. + let tick = sim.time.to_inner() as usize; + if tick + 1 == self.state_per_tick.len() { + return; + } + assert_eq!(tick, self.state_per_tick.len()); + + let mut state = StateAtTime { + cars: BTreeMap::new(), + peds: BTreeMap::new(), + }; + for agent in sim.active_agents().into_iter() { + match agent { + AgentID::Car(id) => { + state.cars.insert(id, sim.get_draw_car(id, map).unwrap()); + } + AgentID::Pedestrian(id) => { + state.peds.insert(id, sim.get_draw_ped(id, map).unwrap()); + } + }; + } + self.state_per_tick.push(state); + } +} + +impl Plugin for TimeTravel { + fn event(&mut self, ctx: PluginCtx) -> bool { + self.record_state(&ctx.primary.sim, &ctx.primary.map); + + false + } +} diff --git a/editor/src/ui.rs b/editor/src/ui.rs index 797a7328c5..a208ab05a9 100644 --- a/editor/src/ui.rs +++ b/editor/src/ui.rs @@ -257,6 +257,7 @@ impl PerMapUI { Box::new(plugins::map_edits::EditsManager::new()), Box::new(plugins::chokepoints::ChokepointsFinder::new()), Box::new(neighborhood_summary), + Box::new(plugins::time_travel::TimeTravel::new()), ], }; (state, plugins) diff --git a/sim/src/physics.rs b/sim/src/physics.rs index a7aa95faf2..e1c20bd052 100644 --- a/sim/src/physics.rs +++ b/sim/src/physics.rs @@ -18,6 +18,10 @@ pub type Acceleration = si::MeterPerSecond2; pub struct Tick(u32); impl Tick { + pub fn to_inner(&self) -> u32 { + self.0 + } + pub fn zero() -> Tick { Tick(0) }