mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-27 16:36:02 +03:00
refactor speed controls. savestate WAY less often, now that the sim is
so fast running.
This commit is contained in:
parent
0c6a93d38f
commit
5e48cde4fc
@ -9,9 +9,9 @@ use crate::ui::UI;
|
||||
use abstutil::elapsed_seconds;
|
||||
use ezgui::{
|
||||
hotkey, Color, EventCtx, EventLoopMode, GfxCtx, HorizontalAlignment, Key, ModalMenu, MultiKey,
|
||||
Text, VerticalAlignment,
|
||||
ScreenPt, Slider, Text, VerticalAlignment,
|
||||
};
|
||||
use geom::{Line, Pt2D};
|
||||
use geom::{Duration, Line, Pt2D};
|
||||
use std::collections::BTreeSet;
|
||||
use std::time::Instant;
|
||||
|
||||
@ -216,3 +216,129 @@ impl Warper {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const ADJUST_SPEED: f64 = 0.1;
|
||||
// TODO hardcoded cap for now...
|
||||
const SPEED_CAP: f64 = 60.0;
|
||||
|
||||
pub struct SpeedControls {
|
||||
slider: Slider,
|
||||
state: State,
|
||||
}
|
||||
|
||||
enum State {
|
||||
Paused,
|
||||
Running {
|
||||
last_step: Instant,
|
||||
speed_description: String,
|
||||
last_measurement: Instant,
|
||||
last_measurement_sim: Duration,
|
||||
},
|
||||
}
|
||||
|
||||
impl SpeedControls {
|
||||
pub fn new(ctx: &mut EventCtx, top_left_at: Option<ScreenPt>) -> SpeedControls {
|
||||
let mut slider = Slider::new(top_left_at);
|
||||
slider.set_percent(ctx, 1.0 / SPEED_CAP);
|
||||
SpeedControls {
|
||||
slider,
|
||||
state: State::Paused,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn modal_status_line(&self) -> String {
|
||||
if let State::Running {
|
||||
ref speed_description,
|
||||
..
|
||||
} = self.state
|
||||
{
|
||||
format!(
|
||||
"Speed: {} / desired {:.2}x",
|
||||
speed_description,
|
||||
self.desired_speed()
|
||||
)
|
||||
} else {
|
||||
format!("Speed: paused / desired {:.2}x", self.desired_speed())
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the amount of simulation time to step, if running.
|
||||
pub fn event(
|
||||
&mut self,
|
||||
ctx: &mut EventCtx,
|
||||
menu: &mut ModalMenu,
|
||||
current_sim_time: Duration,
|
||||
) -> Option<Duration> {
|
||||
let desired_speed = self.desired_speed();
|
||||
if desired_speed != SPEED_CAP && menu.action("speed up") {
|
||||
self.slider
|
||||
.set_percent(ctx, ((desired_speed + ADJUST_SPEED) / SPEED_CAP).min(1.0));
|
||||
} else if desired_speed != 0.0 && menu.action("slow down") {
|
||||
self.slider
|
||||
.set_percent(ctx, ((desired_speed - ADJUST_SPEED) / SPEED_CAP).max(0.0));
|
||||
} else if self.slider.event(ctx) {
|
||||
// Keep going
|
||||
}
|
||||
|
||||
match self.state {
|
||||
State::Paused => {
|
||||
if menu.action("pause/resume") {
|
||||
let now = Instant::now();
|
||||
self.state = State::Running {
|
||||
last_step: now,
|
||||
speed_description: "...".to_string(),
|
||||
last_measurement: now,
|
||||
last_measurement_sim: current_sim_time,
|
||||
};
|
||||
// Sorta hack to trigger EventLoopMode::Animation.
|
||||
return Some(Duration::ZERO);
|
||||
}
|
||||
}
|
||||
State::Running {
|
||||
ref mut last_step,
|
||||
ref mut speed_description,
|
||||
ref mut last_measurement,
|
||||
ref mut last_measurement_sim,
|
||||
} => {
|
||||
if menu.action("pause/resume") {
|
||||
self.state = State::Paused;
|
||||
} else if ctx.input.nonblocking_is_update_event() {
|
||||
ctx.input.use_update_event();
|
||||
let dt = Duration::seconds(elapsed_seconds(*last_step)) * desired_speed;
|
||||
*last_step = Instant::now();
|
||||
|
||||
let dt_descr = Duration::seconds(elapsed_seconds(*last_measurement));
|
||||
if dt_descr >= Duration::seconds(1.0) {
|
||||
*speed_description = format!(
|
||||
"{:.2}x",
|
||||
(current_sim_time - *last_measurement_sim) / dt_descr
|
||||
);
|
||||
*last_measurement = *last_step;
|
||||
*last_measurement_sim = current_sim_time;
|
||||
}
|
||||
return Some(dt);
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn draw(&self, g: &mut GfxCtx) {
|
||||
self.slider.draw(g);
|
||||
}
|
||||
|
||||
pub fn pause(&mut self) {
|
||||
self.state = State::Paused;
|
||||
}
|
||||
|
||||
pub fn is_paused(&self) -> bool {
|
||||
match self.state {
|
||||
State::Paused => true,
|
||||
State::Running { .. } => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn desired_speed(&self) -> f64 {
|
||||
self.slider.get_percent() * SPEED_CAP
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::common::CommonState;
|
||||
use crate::common::{CommonState, SpeedControls};
|
||||
use crate::mission::trips::{clip_trips, Trip};
|
||||
use crate::ui::{ShowEverything, UI};
|
||||
use abstutil::{elapsed_seconds, prettyprint_usize};
|
||||
use abstutil::prettyprint_usize;
|
||||
use ezgui::{
|
||||
hotkey, Color, EventCtx, EventLoopMode, GeomBatch, GfxCtx, Key, ModalMenu, ScreenPt, Slider,
|
||||
Text,
|
||||
@ -9,20 +9,14 @@ use ezgui::{
|
||||
use geom::{Circle, Distance, Duration};
|
||||
use map_model::{PathRequest, LANE_THICKNESS};
|
||||
use popdat::psrc::Mode;
|
||||
use std::time::Instant;
|
||||
|
||||
const ADJUST_SPEED: f64 = 0.1;
|
||||
// TODO hardcoded cap for now...
|
||||
const SPEED_CAP: f64 = 60.0;
|
||||
|
||||
pub struct TripsVisualizer {
|
||||
menu: ModalMenu,
|
||||
trips: Vec<Trip>,
|
||||
time_slider: Slider,
|
||||
speed_slider: Slider,
|
||||
speed: SpeedControls,
|
||||
|
||||
active_trips: Vec<usize>,
|
||||
running: Option<Instant>,
|
||||
}
|
||||
|
||||
enum MaybeTrip {
|
||||
@ -62,10 +56,6 @@ impl TripsVisualizer {
|
||||
final_trips
|
||||
});
|
||||
|
||||
// TODO It'd be awesome to use the generic timer controls for this
|
||||
// TODO hardcoding placement...
|
||||
let mut speed_slider = Slider::new(Some(ScreenPt::new(500.0, 0.0)));
|
||||
speed_slider.set_percent(ctx, 1.0 / SPEED_CAP);
|
||||
TripsVisualizer {
|
||||
menu: ModalMenu::new(
|
||||
"Trips Visualizer",
|
||||
@ -83,10 +73,10 @@ impl TripsVisualizer {
|
||||
],
|
||||
ctx,
|
||||
),
|
||||
running: None,
|
||||
trips,
|
||||
time_slider: Slider::new(None),
|
||||
speed_slider,
|
||||
// TODO hardcoding placement...
|
||||
speed: SpeedControls::new(ctx, Some(ScreenPt::new(500.0, 0.0))),
|
||||
active_trips: Vec::new(),
|
||||
}
|
||||
}
|
||||
@ -98,7 +88,6 @@ impl TripsVisualizer {
|
||||
// Returns None if the we're done
|
||||
pub fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI) -> Option<EventLoopMode> {
|
||||
let time = self.current_time();
|
||||
let desired_speed = self.speed_slider.get_percent() * SPEED_CAP;
|
||||
|
||||
let mut txt = Text::prompt("Trips Visualizer");
|
||||
txt.add_line(format!(
|
||||
@ -106,12 +95,7 @@ impl TripsVisualizer {
|
||||
prettyprint_usize(self.active_trips.len())
|
||||
));
|
||||
txt.add_line(format!("At {}", time));
|
||||
txt.add_line(format!("Speed: {:.2}x", desired_speed));
|
||||
if self.running.is_some() {
|
||||
txt.add_line("Playing".to_string());
|
||||
} else {
|
||||
txt.add_line("Paused".to_string());
|
||||
}
|
||||
txt.add_line(self.speed.modal_status_line());
|
||||
self.menu.handle_event(ctx, Some(txt));
|
||||
ctx.canvas.handle_event(ctx.input);
|
||||
|
||||
@ -122,22 +106,6 @@ impl TripsVisualizer {
|
||||
let ten_secs = Duration::seconds(10.0);
|
||||
let thirty_mins = Duration::minutes(30);
|
||||
|
||||
if desired_speed != SPEED_CAP && self.menu.action("speed up") {
|
||||
self.speed_slider
|
||||
.set_percent(ctx, ((desired_speed + ADJUST_SPEED) / SPEED_CAP).min(1.0));
|
||||
} else if desired_speed != 0.0 && self.menu.action("slow down") {
|
||||
self.speed_slider
|
||||
.set_percent(ctx, ((desired_speed - ADJUST_SPEED) / SPEED_CAP).max(0.0));
|
||||
} else if self.speed_slider.event(ctx) {
|
||||
// Keep going
|
||||
} else if self.menu.action("pause/resume") {
|
||||
if self.running.is_some() {
|
||||
self.running = None;
|
||||
} else {
|
||||
self.running = Some(Instant::now());
|
||||
}
|
||||
}
|
||||
|
||||
if self.menu.action("quit") {
|
||||
return None;
|
||||
} else if time != last_time && self.menu.action("forwards 10 seconds") {
|
||||
@ -158,17 +126,11 @@ impl TripsVisualizer {
|
||||
self.time_slider.set_percent(ctx, 1.0);
|
||||
} else if self.time_slider.event(ctx) {
|
||||
// Value changed, fall-through
|
||||
} else if let Some(last_step) = self.running {
|
||||
if ctx.input.nonblocking_is_update_event() {
|
||||
ctx.input.use_update_event();
|
||||
let dt = Duration::seconds(elapsed_seconds(last_step)) * desired_speed;
|
||||
self.time_slider
|
||||
.set_percent(ctx, ((time + dt) / last_time).min(1.0));
|
||||
self.running = Some(Instant::now());
|
||||
// Value changed, fall-through
|
||||
} else {
|
||||
return Some(EventLoopMode::Animation);
|
||||
}
|
||||
} else if let Some(dt) = self.speed.event(ctx, &mut self.menu, time) {
|
||||
// TODO Speed description is briefly weird when we jump backwards with the other
|
||||
// control.
|
||||
self.time_slider
|
||||
.set_percent(ctx, ((time + dt) / last_time).min(1.0));
|
||||
} else {
|
||||
return Some(EventLoopMode::InputOnly);
|
||||
}
|
||||
@ -183,10 +145,10 @@ impl TripsVisualizer {
|
||||
.map(|(idx, _)| idx)
|
||||
.collect();
|
||||
|
||||
if self.running.is_some() {
|
||||
Some(EventLoopMode::Animation)
|
||||
} else {
|
||||
if self.speed.is_paused() {
|
||||
Some(EventLoopMode::InputOnly)
|
||||
} else {
|
||||
Some(EventLoopMode::Animation)
|
||||
}
|
||||
}
|
||||
|
||||
@ -220,7 +182,7 @@ impl TripsVisualizer {
|
||||
|
||||
self.menu.draw(g);
|
||||
self.time_slider.draw(g);
|
||||
self.speed_slider.draw(g);
|
||||
self.speed.draw(g);
|
||||
CommonState::draw_osd(g, ui, ui.primary.current_selection);
|
||||
}
|
||||
}
|
||||
|
@ -4,24 +4,18 @@ mod show_activity;
|
||||
mod spawner;
|
||||
mod time_travel;
|
||||
|
||||
use crate::common::CommonState;
|
||||
use crate::common::{CommonState, SpeedControls};
|
||||
use crate::debug::DebugMode;
|
||||
use crate::edit::EditMode;
|
||||
use crate::game::{GameState, Mode};
|
||||
use crate::render::DrawOptions;
|
||||
use crate::ui::ShowEverything;
|
||||
use abstutil::elapsed_seconds;
|
||||
use ezgui::{hotkey, lctrl, EventCtx, EventLoopMode, GfxCtx, Key, ModalMenu, Slider, Text, Wizard};
|
||||
use ezgui::{hotkey, lctrl, EventCtx, EventLoopMode, GfxCtx, Key, ModalMenu, Text, Wizard};
|
||||
use geom::Duration;
|
||||
use sim::{Benchmark, Sim, TripID};
|
||||
use std::time::Instant;
|
||||
|
||||
const ADJUST_SPEED: f64 = 0.1;
|
||||
// TODO hardcoded cap for now...
|
||||
const SPEED_CAP: f64 = 60.0;
|
||||
use sim::{Sim, TripID};
|
||||
|
||||
pub struct SandboxMode {
|
||||
speed_slider: Slider,
|
||||
speed: SpeedControls,
|
||||
following: Option<TripID>,
|
||||
route_viewer: route_viewer::RouteViewer,
|
||||
show_activity: show_activity::ShowActivity,
|
||||
@ -33,12 +27,7 @@ pub struct SandboxMode {
|
||||
}
|
||||
|
||||
enum State {
|
||||
Paused,
|
||||
Running {
|
||||
last_step: Instant,
|
||||
benchmark: Benchmark,
|
||||
speed: String,
|
||||
},
|
||||
Playing,
|
||||
Spawning(spawner::AgentSpawner),
|
||||
TimeTraveling,
|
||||
ExploringRoute(route_explorer::RouteExplorer),
|
||||
@ -46,11 +35,9 @@ enum State {
|
||||
|
||||
impl SandboxMode {
|
||||
pub fn new(ctx: &mut EventCtx) -> SandboxMode {
|
||||
let mut speed_slider = Slider::new(None);
|
||||
speed_slider.set_percent(ctx, 1.0 / SPEED_CAP);
|
||||
SandboxMode {
|
||||
speed_slider,
|
||||
state: State::Paused,
|
||||
speed: SpeedControls::new(ctx, None),
|
||||
state: State::Playing,
|
||||
following: None,
|
||||
route_viewer: route_viewer::RouteViewer::Inactive,
|
||||
show_activity: show_activity::ShowActivity::Inactive,
|
||||
@ -61,12 +48,12 @@ impl SandboxMode {
|
||||
vec![
|
||||
vec![
|
||||
(hotkey(Key::Escape), "quit"),
|
||||
(hotkey(Key::LeftBracket), "slow down sim"),
|
||||
(hotkey(Key::RightBracket), "speed up sim"),
|
||||
(hotkey(Key::RightBracket), "speed up"),
|
||||
(hotkey(Key::LeftBracket), "slow down"),
|
||||
(hotkey(Key::Space), "pause/resume"),
|
||||
(hotkey(Key::O), "save sim state"),
|
||||
(hotkey(Key::Y), "load previous sim state"),
|
||||
(hotkey(Key::U), "load next sim state"),
|
||||
(hotkey(Key::Space), "run/pause sim"),
|
||||
(hotkey(Key::M), "step forwards 0.1s"),
|
||||
(hotkey(Key::N), "step forwards 10 mins"),
|
||||
(hotkey(Key::X), "reset sim"),
|
||||
@ -91,152 +78,145 @@ impl SandboxMode {
|
||||
|
||||
pub fn event(state: &mut GameState, ctx: &mut EventCtx) -> EventLoopMode {
|
||||
match state.mode {
|
||||
Mode::Sandbox(ref mut mode) => {
|
||||
if let State::Spawning(ref mut spawner) = mode.state {
|
||||
Mode::Sandbox(ref mut mode) => match mode.state {
|
||||
State::Spawning(ref mut spawner) => {
|
||||
if spawner.event(ctx, &mut state.ui) {
|
||||
mode.state = State::Paused;
|
||||
mode.state = State::Playing;
|
||||
mode.speed.pause();
|
||||
}
|
||||
return EventLoopMode::InputOnly;
|
||||
EventLoopMode::InputOnly
|
||||
}
|
||||
if let State::TimeTraveling = mode.state {
|
||||
State::TimeTraveling => {
|
||||
if mode.time_travel.event(ctx) {
|
||||
mode.state = State::Paused;
|
||||
mode.state = State::Playing;
|
||||
mode.speed.pause();
|
||||
}
|
||||
return EventLoopMode::InputOnly;
|
||||
EventLoopMode::InputOnly
|
||||
}
|
||||
mode.time_travel.record(&state.ui);
|
||||
if let State::ExploringRoute(ref mut explorer) = mode.state {
|
||||
State::ExploringRoute(ref mut explorer) => {
|
||||
if let Some(mode) = explorer.event(ctx, &mut state.ui) {
|
||||
return mode;
|
||||
}
|
||||
mode.state = State::Paused;
|
||||
return EventLoopMode::InputOnly;
|
||||
}
|
||||
|
||||
let desired_speed = mode.speed_slider.get_percent() * SPEED_CAP;
|
||||
|
||||
let mut txt = Text::prompt("Sandbox Mode");
|
||||
txt.add_line(state.ui.primary.sim.summary());
|
||||
if let State::Running { ref speed, .. } = mode.state {
|
||||
txt.add_line(format!(
|
||||
"Speed: {0} / desired {1:.2}x",
|
||||
speed, desired_speed
|
||||
));
|
||||
} else {
|
||||
txt.add_line(format!("Speed: paused / desired {0:.2}x", desired_speed));
|
||||
}
|
||||
if let Some(trip) = mode.following {
|
||||
txt.add_line(format!("Following {}", trip));
|
||||
}
|
||||
match mode.route_viewer {
|
||||
route_viewer::RouteViewer::Active(_, trip, _) => {
|
||||
txt.add_line(format!("Showing {}'s route", trip));
|
||||
}
|
||||
route_viewer::RouteViewer::DebugAllRoutes(_, _) => {
|
||||
txt.add_line("Showing all routes".to_string());
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
match mode.show_activity {
|
||||
show_activity::ShowActivity::Inactive => {}
|
||||
_ => {
|
||||
txt.add_line("Showing active traffic".to_string());
|
||||
mode
|
||||
} else {
|
||||
mode.state = State::Playing;
|
||||
mode.speed.pause();
|
||||
EventLoopMode::InputOnly
|
||||
}
|
||||
}
|
||||
mode.menu.handle_event(ctx, Some(txt));
|
||||
State::Playing => {
|
||||
mode.time_travel.record(&state.ui);
|
||||
|
||||
ctx.canvas.handle_event(ctx.input);
|
||||
state.ui.primary.current_selection = state.ui.handle_mouseover(
|
||||
ctx,
|
||||
&state.ui.primary.sim,
|
||||
&ShowEverything::new(),
|
||||
false,
|
||||
);
|
||||
if let Some(evmode) = mode.common.event(ctx, &mut state.ui, &mut mode.menu) {
|
||||
return evmode;
|
||||
}
|
||||
let mut txt = Text::prompt("Sandbox Mode");
|
||||
txt.add_line(state.ui.primary.sim.summary());
|
||||
txt.add_line(mode.speed.modal_status_line());
|
||||
if let Some(trip) = mode.following {
|
||||
txt.add_line(format!("Following {}", trip));
|
||||
}
|
||||
match mode.route_viewer {
|
||||
route_viewer::RouteViewer::Active(_, trip, _) => {
|
||||
txt.add_line(format!("Showing {}'s route", trip));
|
||||
}
|
||||
route_viewer::RouteViewer::DebugAllRoutes(_, _) => {
|
||||
txt.add_line("Showing all routes".to_string());
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
match mode.show_activity {
|
||||
show_activity::ShowActivity::Inactive => {}
|
||||
_ => {
|
||||
txt.add_line("Showing active traffic".to_string());
|
||||
}
|
||||
}
|
||||
mode.menu.handle_event(ctx, Some(txt));
|
||||
|
||||
if let Some(spawner) =
|
||||
spawner::AgentSpawner::new(ctx, &mut state.ui, &mut mode.menu)
|
||||
{
|
||||
mode.state = State::Spawning(spawner);
|
||||
return EventLoopMode::InputOnly;
|
||||
}
|
||||
if let Some(explorer) = route_explorer::RouteExplorer::new(ctx, &state.ui) {
|
||||
mode.state = State::ExploringRoute(explorer);
|
||||
return EventLoopMode::InputOnly;
|
||||
}
|
||||
ctx.canvas.handle_event(ctx.input);
|
||||
state.ui.primary.current_selection = state.ui.handle_mouseover(
|
||||
ctx,
|
||||
&state.ui.primary.sim,
|
||||
&ShowEverything::new(),
|
||||
false,
|
||||
);
|
||||
if let Some(evmode) = mode.common.event(ctx, &mut state.ui, &mut mode.menu) {
|
||||
return evmode;
|
||||
}
|
||||
|
||||
if mode.following.is_none() {
|
||||
if let Some(agent) = state
|
||||
.ui
|
||||
.primary
|
||||
.current_selection
|
||||
.and_then(|id| id.agent_id())
|
||||
if let Some(spawner) =
|
||||
spawner::AgentSpawner::new(ctx, &mut state.ui, &mut mode.menu)
|
||||
{
|
||||
if let Some(trip) = state.ui.primary.sim.agent_to_trip(agent) {
|
||||
if ctx
|
||||
.input
|
||||
.contextual_action(Key::F, &format!("follow {}", agent))
|
||||
{
|
||||
mode.following = Some(trip);
|
||||
mode.state = State::Spawning(spawner);
|
||||
return EventLoopMode::InputOnly;
|
||||
}
|
||||
if let Some(explorer) = route_explorer::RouteExplorer::new(ctx, &state.ui) {
|
||||
mode.state = State::ExploringRoute(explorer);
|
||||
return EventLoopMode::InputOnly;
|
||||
}
|
||||
|
||||
if mode.following.is_none() {
|
||||
if let Some(agent) = state
|
||||
.ui
|
||||
.primary
|
||||
.current_selection
|
||||
.and_then(|id| id.agent_id())
|
||||
{
|
||||
if let Some(trip) = state.ui.primary.sim.agent_to_trip(agent) {
|
||||
if ctx
|
||||
.input
|
||||
.contextual_action(Key::F, &format!("follow {}", agent))
|
||||
{
|
||||
mode.following = Some(trip);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(trip) = mode.following {
|
||||
if let Some(pt) = state
|
||||
.ui
|
||||
.primary
|
||||
.sim
|
||||
.get_canonical_pt_per_trip(trip, &state.ui.primary.map)
|
||||
if let Some(trip) = mode.following {
|
||||
if let Some(pt) = state
|
||||
.ui
|
||||
.primary
|
||||
.sim
|
||||
.get_canonical_pt_per_trip(trip, &state.ui.primary.map)
|
||||
{
|
||||
ctx.canvas.center_on_map_pt(pt);
|
||||
} else {
|
||||
// TODO ideally they wouldnt vanish for so long according to
|
||||
// get_canonical_point_for_trip
|
||||
println!("{} is gone... temporarily or not?", trip);
|
||||
}
|
||||
if mode.menu.action("stop following agent") {
|
||||
mode.following = None;
|
||||
}
|
||||
}
|
||||
mode.route_viewer.event(ctx, &mut state.ui, &mut mode.menu);
|
||||
mode.show_activity.event(ctx, &mut state.ui, &mut mode.menu);
|
||||
if mode.menu.action("start time traveling") {
|
||||
mode.state = State::TimeTraveling;
|
||||
mode.time_travel.start(ctx, &state.ui);
|
||||
return EventLoopMode::InputOnly;
|
||||
}
|
||||
|
||||
if mode.menu.action("quit") {
|
||||
state.mode = Mode::SplashScreen(Wizard::new(), None);
|
||||
return EventLoopMode::InputOnly;
|
||||
}
|
||||
if mode.menu.action("debug mode") {
|
||||
state.mode = Mode::Debug(DebugMode::new(ctx, &state.ui));
|
||||
return EventLoopMode::InputOnly;
|
||||
}
|
||||
if mode.menu.action("edit mode") {
|
||||
state.mode = Mode::Edit(EditMode::new(ctx, &mut state.ui));
|
||||
return EventLoopMode::InputOnly;
|
||||
}
|
||||
|
||||
if let Some(dt) =
|
||||
mode.speed
|
||||
.event(ctx, &mut mode.menu, state.ui.primary.sim.time())
|
||||
{
|
||||
ctx.canvas.center_on_map_pt(pt);
|
||||
} else {
|
||||
// TODO ideally they wouldnt vanish for so long according to
|
||||
// get_canonical_point_for_trip
|
||||
println!("{} is gone... temporarily or not?", trip);
|
||||
state.ui.primary.sim.step(&state.ui.primary.map, dt);
|
||||
//*ctx.recalculate_current_selection = true;
|
||||
}
|
||||
if mode.menu.action("stop following agent") {
|
||||
mode.following = None;
|
||||
}
|
||||
}
|
||||
mode.route_viewer.event(ctx, &mut state.ui, &mut mode.menu);
|
||||
mode.show_activity.event(ctx, &mut state.ui, &mut mode.menu);
|
||||
if mode.menu.action("start time traveling") {
|
||||
mode.state = State::TimeTraveling;
|
||||
mode.time_travel.start(ctx, &state.ui);
|
||||
return EventLoopMode::InputOnly;
|
||||
}
|
||||
|
||||
if mode.menu.action("quit") {
|
||||
state.mode = Mode::SplashScreen(Wizard::new(), None);
|
||||
return EventLoopMode::InputOnly;
|
||||
}
|
||||
if mode.menu.action("debug mode") {
|
||||
state.mode = Mode::Debug(DebugMode::new(ctx, &state.ui));
|
||||
return EventLoopMode::InputOnly;
|
||||
}
|
||||
if mode.menu.action("edit mode") {
|
||||
state.mode = Mode::Edit(EditMode::new(ctx, &mut state.ui));
|
||||
return EventLoopMode::InputOnly;
|
||||
}
|
||||
|
||||
if desired_speed != SPEED_CAP && mode.menu.action("speed up sim") {
|
||||
mode.speed_slider
|
||||
.set_percent(ctx, ((desired_speed + ADJUST_SPEED) / SPEED_CAP).min(1.0));
|
||||
} else if desired_speed != 0.0 && mode.menu.action("slow down sim") {
|
||||
mode.speed_slider
|
||||
.set_percent(ctx, ((desired_speed - ADJUST_SPEED) / SPEED_CAP).max(0.0));
|
||||
} else if mode.speed_slider.event(ctx) {
|
||||
// Keep going
|
||||
}
|
||||
|
||||
match mode.state {
|
||||
State::Paused => {
|
||||
if mode.speed.is_paused() {
|
||||
if !state.ui.primary.sim.is_empty() && mode.menu.action("reset sim") {
|
||||
state.ui.primary.reset_sim();
|
||||
mode.state = State::Paused;
|
||||
mode.state = State::Playing;
|
||||
mode.following = None;
|
||||
mode.route_viewer = route_viewer::RouteViewer::Inactive;
|
||||
mode.show_activity = show_activity::ShowActivity::Inactive;
|
||||
@ -281,13 +261,7 @@ impl SandboxMode {
|
||||
}
|
||||
}
|
||||
|
||||
if mode.menu.action("run/pause sim") {
|
||||
mode.state = State::Running {
|
||||
last_step: Instant::now(),
|
||||
benchmark: state.ui.primary.sim.start_benchmark(),
|
||||
speed: "...".to_string(),
|
||||
};
|
||||
} else if mode.menu.action("step forwards 0.1s") {
|
||||
if mode.menu.action("step forwards 0.1s") {
|
||||
state
|
||||
.ui
|
||||
.primary
|
||||
@ -303,33 +277,11 @@ impl SandboxMode {
|
||||
//*ctx.recalculate_current_selection = true;
|
||||
}
|
||||
EventLoopMode::InputOnly
|
||||
}
|
||||
State::Running {
|
||||
ref mut last_step,
|
||||
ref mut benchmark,
|
||||
ref mut speed,
|
||||
} => {
|
||||
if mode.menu.action("run/pause sim") {
|
||||
mode.state = State::Paused;
|
||||
} else if ctx.input.nonblocking_is_update_event() {
|
||||
ctx.input.use_update_event();
|
||||
let dt = Duration::seconds(elapsed_seconds(*last_step)) * desired_speed;
|
||||
|
||||
state.ui.primary.sim.step(&state.ui.primary.map, dt);
|
||||
//*ctx.recalculate_current_selection = true;
|
||||
*last_step = Instant::now();
|
||||
|
||||
if benchmark.has_real_time_passed(Duration::seconds(1.0)) {
|
||||
*speed = state.ui.primary.sim.measure_speed(benchmark, false);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
EventLoopMode::Animation
|
||||
}
|
||||
State::Spawning(_) => unreachable!(),
|
||||
State::TimeTraveling => unreachable!(),
|
||||
State::ExploringRoute(_) => unreachable!(),
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
@ -369,7 +321,7 @@ impl SandboxMode {
|
||||
mode.route_viewer.draw(g, &state.ui);
|
||||
mode.show_activity.draw(g, &state.ui);
|
||||
mode.menu.draw(g);
|
||||
mode.speed_slider.draw(g);
|
||||
mode.speed.draw(g);
|
||||
}
|
||||
},
|
||||
_ => unreachable!(),
|
||||
|
@ -407,7 +407,7 @@ impl PerMapUI {
|
||||
pub fn new(flags: Flags, cs: &ColorScheme, ctx: &mut EventCtx) -> PerMapUI {
|
||||
let (map, sim, draw_map) = ctx.loading_screen("load map", |ctx, timer| {
|
||||
let mut mem = MeasureMemory::new();
|
||||
let (map, sim, _) = flags.sim_flags.load(Some(Duration::seconds(30.0)), timer);
|
||||
let (map, sim, _) = flags.sim_flags.load(Some(Duration::minutes(30)), timer);
|
||||
mem.reset("Map and Sim", timer);
|
||||
|
||||
timer.start("draw_map");
|
||||
|
Loading…
Reference in New Issue
Block a user