mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-28 20:29:04 +03:00
refactoring a WizardState to replace LOTS of boilerplate. converting
some easy first cases
This commit is contained in:
parent
950fb65bea
commit
136ca2d7ab
@ -1,9 +1,8 @@
|
||||
use crate::game::{State, Transition};
|
||||
use crate::game::{State, Transition, WizardState};
|
||||
use crate::ui::PerMapUI;
|
||||
use crate::ui::UI;
|
||||
use ezgui::{
|
||||
hotkey, EventCtx, GfxCtx, HorizontalAlignment, Key, ModalMenu, Text, VerticalAlignment, Wizard,
|
||||
WrappedWizard,
|
||||
};
|
||||
use geom::Duration;
|
||||
use itertools::Itertools;
|
||||
@ -83,19 +82,13 @@ impl Scoreboard {
|
||||
}
|
||||
|
||||
impl State for Scoreboard {
|
||||
fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI) -> Transition {
|
||||
fn event(&mut self, ctx: &mut EventCtx, _: &mut UI) -> Transition {
|
||||
self.menu.handle_event(ctx, None);
|
||||
if self.menu.action("quit") {
|
||||
return Transition::Pop;
|
||||
}
|
||||
if self.menu.action("browse trips") {
|
||||
return Transition::Push(Box::new(BrowseTrips {
|
||||
trips: CompareTrips::new(
|
||||
ui.primary.sim.get_finished_trips(),
|
||||
ui.secondary.as_ref().unwrap().sim.get_finished_trips(),
|
||||
),
|
||||
wizard: Wizard::new(),
|
||||
}));
|
||||
return Transition::Push(WizardState::new(Box::new(browse_trips)));
|
||||
}
|
||||
Transition::Keep
|
||||
}
|
||||
@ -109,28 +102,8 @@ impl State for Scoreboard {
|
||||
}
|
||||
}
|
||||
|
||||
struct BrowseTrips {
|
||||
trips: CompareTrips,
|
||||
wizard: Wizard,
|
||||
}
|
||||
|
||||
impl State for BrowseTrips {
|
||||
fn event(&mut self, ctx: &mut EventCtx, _: &mut UI) -> Transition {
|
||||
if pick_trip(&self.trips, &mut self.wizard.wrap(ctx)).is_some() {
|
||||
// TODO show more details...
|
||||
return Transition::Pop;
|
||||
} else if self.wizard.aborted() {
|
||||
return Transition::Pop;
|
||||
}
|
||||
Transition::Keep
|
||||
}
|
||||
|
||||
fn draw(&self, g: &mut GfxCtx, _: &UI) {
|
||||
self.wizard.draw(g);
|
||||
}
|
||||
}
|
||||
|
||||
fn pick_trip(trips: &CompareTrips, wizard: &mut WrappedWizard) -> Option<TripID> {
|
||||
fn browse_trips(wiz: &mut Wizard, ctx: &mut EventCtx, ui: &mut UI) -> Option<Transition> {
|
||||
let mut wizard = wiz.wrap(ctx);
|
||||
let mode = wizard
|
||||
.choose_something_no_keys::<TripMode>(
|
||||
"Browse which trips?",
|
||||
@ -145,6 +118,10 @@ fn pick_trip(trips: &CompareTrips, wizard: &mut WrappedWizard) -> Option<TripID>
|
||||
)?
|
||||
.1;
|
||||
// TODO Ewwww. Can't do this inside choices_generator because trips isn't &'a static.
|
||||
let trips = CompareTrips::new(
|
||||
ui.primary.sim.get_finished_trips(),
|
||||
ui.secondary.as_ref().unwrap().sim.get_finished_trips(),
|
||||
);
|
||||
let mut filtered: Vec<&(TripID, TripMode, Duration, Duration)> = trips
|
||||
.finished_trips
|
||||
.iter()
|
||||
@ -156,12 +133,12 @@ fn pick_trip(trips: &CompareTrips, wizard: &mut WrappedWizard) -> Option<TripID>
|
||||
.into_iter()
|
||||
.map(|(id, _, t1, t2)| (format!("{} taking {} vs {}", id, t1, t2), *id))
|
||||
.collect();
|
||||
wizard
|
||||
.choose_something_no_keys::<TripID>(
|
||||
"Examine which trip?",
|
||||
Box::new(move || choices.clone()),
|
||||
)
|
||||
.map(|(_, id)| id)
|
||||
wizard.choose_something_no_keys::<TripID>(
|
||||
"Examine which trip?",
|
||||
Box::new(move || choices.clone()),
|
||||
)?;
|
||||
// TODO show more details...
|
||||
Some(Transition::Pop)
|
||||
}
|
||||
|
||||
pub struct CompareTrips {
|
||||
|
@ -3,7 +3,7 @@ mod traffic_signals;
|
||||
|
||||
use crate::common::CommonState;
|
||||
use crate::debug::DebugMode;
|
||||
use crate::game::{State, Transition};
|
||||
use crate::game::{State, Transition, WizardState};
|
||||
use crate::helpers::{ColorScheme, ID};
|
||||
use crate::render::{
|
||||
DrawCtx, DrawIntersection, DrawLane, DrawMap, DrawOptions, DrawTurn, Renderable,
|
||||
@ -99,13 +99,9 @@ impl State for EditMode {
|
||||
|
||||
// TODO Only if current edits are unsaved
|
||||
if self.menu.action("save edits") {
|
||||
return Transition::Push(Box::new(Saving {
|
||||
wizard: Wizard::new(),
|
||||
}));
|
||||
return Transition::Push(WizardState::new(Box::new(save_edits)));
|
||||
} else if self.menu.action("load different edits") {
|
||||
return Transition::Push(Box::new(Loading {
|
||||
wizard: Wizard::new(),
|
||||
}));
|
||||
return Transition::Push(WizardState::new(Box::new(load_edits)));
|
||||
}
|
||||
|
||||
if let Some(ID::Lane(id)) = ui.primary.current_selection {
|
||||
@ -292,79 +288,10 @@ impl State for EditMode {
|
||||
}
|
||||
}
|
||||
|
||||
struct Saving {
|
||||
wizard: Wizard,
|
||||
}
|
||||
fn save_edits(wiz: &mut Wizard, ctx: &mut EventCtx, ui: &mut UI) -> Option<Transition> {
|
||||
let map = &mut ui.primary.map;
|
||||
let mut wizard = wiz.wrap(ctx);
|
||||
|
||||
impl State for Saving {
|
||||
fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI) -> Transition {
|
||||
ctx.canvas.handle_event(ctx.input);
|
||||
if save_edits(self.wizard.wrap(ctx), &mut ui.primary.map).is_some() || self.wizard.aborted()
|
||||
{
|
||||
Transition::Pop
|
||||
} else {
|
||||
Transition::Keep
|
||||
}
|
||||
}
|
||||
|
||||
fn draw(&self, g: &mut GfxCtx, _: &UI) {
|
||||
// TODO Still draw the diffs, yo
|
||||
self.wizard.draw(g);
|
||||
}
|
||||
}
|
||||
|
||||
struct Loading {
|
||||
wizard: Wizard,
|
||||
}
|
||||
|
||||
impl State for Loading {
|
||||
fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI) -> Transition {
|
||||
ctx.canvas.handle_event(ctx.input);
|
||||
if let Some(new_edits) = load_edits(
|
||||
&ui.primary.map,
|
||||
&mut self.wizard.wrap(ctx),
|
||||
"Load which map edits?",
|
||||
) {
|
||||
apply_map_edits(&mut ui.primary, &ui.cs, ctx, new_edits);
|
||||
Transition::Pop
|
||||
} else if self.wizard.aborted() {
|
||||
Transition::Pop
|
||||
} else {
|
||||
Transition::Keep
|
||||
}
|
||||
}
|
||||
|
||||
fn draw(&self, g: &mut GfxCtx, _: &UI) {
|
||||
// TODO Still draw the diffs, yo
|
||||
self.wizard.draw(g);
|
||||
}
|
||||
}
|
||||
|
||||
struct BulkEditLanes {
|
||||
road: RoadID,
|
||||
wizard: Wizard,
|
||||
}
|
||||
|
||||
impl State for BulkEditLanes {
|
||||
fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI) -> Transition {
|
||||
ctx.canvas.handle_event(ctx.input);
|
||||
if let Some(edits) = bulk_edit(self.road, &mut self.wizard.wrap(ctx), &ui.primary.map) {
|
||||
apply_map_edits(&mut ui.primary, &ui.cs, ctx, edits);
|
||||
Transition::Pop
|
||||
} else if self.wizard.aborted() {
|
||||
Transition::Pop
|
||||
} else {
|
||||
Transition::Keep
|
||||
}
|
||||
}
|
||||
|
||||
fn draw(&self, g: &mut GfxCtx, _: &UI) {
|
||||
// TODO Still draw the diffs, yo
|
||||
self.wizard.draw(g);
|
||||
}
|
||||
}
|
||||
|
||||
fn save_edits(mut wizard: WrappedWizard, map: &mut Map) -> Option<()> {
|
||||
let rename = if map.get_edits().edits_name == "no_edits" {
|
||||
Some(wizard.input_string("Name these map edits")?)
|
||||
} else {
|
||||
@ -386,7 +313,25 @@ fn save_edits(mut wizard: WrappedWizard, map: &mut Map) -> Option<()> {
|
||||
}
|
||||
map.get_edits().save();
|
||||
}
|
||||
Some(())
|
||||
Some(Transition::Pop)
|
||||
}
|
||||
|
||||
fn load_edits(wiz: &mut Wizard, ctx: &mut EventCtx, ui: &mut UI) -> Option<Transition> {
|
||||
let map = &mut ui.primary.map;
|
||||
let mut wizard = wiz.wrap(ctx);
|
||||
|
||||
// TODO Exclude current
|
||||
let map_name = map.get_name().to_string();
|
||||
let (_, new_edits) = wizard.choose_something_no_keys::<MapEdits>(
|
||||
"Load which map edits?",
|
||||
Box::new(move || {
|
||||
let mut list = abstutil::load_all_objects("edits", &map_name);
|
||||
list.push(("no_edits".to_string(), MapEdits::new(map_name.clone())));
|
||||
list
|
||||
}),
|
||||
)?;
|
||||
apply_map_edits(&mut ui.primary, &ui.cs, ctx, new_edits);
|
||||
Some(Transition::Pop)
|
||||
}
|
||||
|
||||
// For lane editing
|
||||
@ -532,19 +477,28 @@ pub fn apply_map_edits(
|
||||
bundle.map.simplify_edits(&mut timer);
|
||||
}
|
||||
|
||||
fn load_edits(map: &Map, wizard: &mut WrappedWizard, query: &str) -> Option<MapEdits> {
|
||||
// TODO Exclude current?
|
||||
let map_name = map.get_name().to_string();
|
||||
wizard
|
||||
.choose_something_no_keys::<MapEdits>(
|
||||
query,
|
||||
Box::new(move || {
|
||||
let mut list = abstutil::load_all_objects("edits", &map_name);
|
||||
list.push(("no_edits".to_string(), MapEdits::new(map_name.clone())));
|
||||
list
|
||||
}),
|
||||
)
|
||||
.map(|(_, e)| e)
|
||||
struct BulkEditLanes {
|
||||
road: RoadID,
|
||||
wizard: Wizard,
|
||||
}
|
||||
|
||||
impl State for BulkEditLanes {
|
||||
fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI) -> Transition {
|
||||
ctx.canvas.handle_event(ctx.input);
|
||||
if let Some(edits) = bulk_edit(self.road, &mut self.wizard.wrap(ctx), &ui.primary.map) {
|
||||
apply_map_edits(&mut ui.primary, &ui.cs, ctx, edits);
|
||||
Transition::Pop
|
||||
} else if self.wizard.aborted() {
|
||||
Transition::Pop
|
||||
} else {
|
||||
Transition::Keep
|
||||
}
|
||||
}
|
||||
|
||||
fn draw(&self, g: &mut GfxCtx, _: &UI) {
|
||||
// TODO Still draw the diffs, yo
|
||||
self.wizard.draw(g);
|
||||
}
|
||||
}
|
||||
|
||||
fn bulk_edit(r: RoadID, wizard: &mut WrappedWizard, map: &Map) -> Option<MapEdits> {
|
||||
|
@ -2,7 +2,7 @@ use crate::render::DrawOptions;
|
||||
use crate::sandbox::SandboxMode;
|
||||
use crate::splash_screen::SplashScreen;
|
||||
use crate::ui::{Flags, ShowEverything, UI};
|
||||
use ezgui::{Canvas, EventCtx, EventLoopMode, GfxCtx, GUI};
|
||||
use ezgui::{Canvas, EventCtx, EventLoopMode, GfxCtx, Wizard, GUI};
|
||||
|
||||
// This is the top-level of the GUI logic. This module should just manage interactions between the
|
||||
// top-level game states.
|
||||
@ -195,3 +195,38 @@ pub enum Transition {
|
||||
PushWithMode(Box<State>, EventLoopMode),
|
||||
ReplaceWithMode(Box<State>, EventLoopMode),
|
||||
}
|
||||
|
||||
// TODO Maybe let callers stash expensive data computed once here, and let the cb borrow it.
|
||||
// Use cases: both BrowseTrips's
|
||||
pub struct WizardState {
|
||||
wizard: Wizard,
|
||||
// Returning None means stay in this WizardState
|
||||
cb: Box<Fn(&mut Wizard, &mut EventCtx, &mut UI) -> Option<Transition>>,
|
||||
}
|
||||
|
||||
impl WizardState {
|
||||
pub fn new(
|
||||
cb: Box<Fn(&mut Wizard, &mut EventCtx, &mut UI) -> Option<Transition>>,
|
||||
) -> Box<State> {
|
||||
Box::new(WizardState {
|
||||
wizard: Wizard::new(),
|
||||
cb,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl State for WizardState {
|
||||
fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI) -> Transition {
|
||||
ctx.canvas.handle_event(ctx.input);
|
||||
if let Some(t) = (self.cb)(&mut self.wizard, ctx, ui) {
|
||||
return t;
|
||||
} else if self.wizard.aborted() {
|
||||
return Transition::Pop;
|
||||
}
|
||||
Transition::Keep
|
||||
}
|
||||
|
||||
fn draw(&self, g: &mut GfxCtx, _: &UI) {
|
||||
self.wizard.draw(g);
|
||||
}
|
||||
}
|
||||
|
@ -7,11 +7,9 @@ use crate::common::{
|
||||
};
|
||||
use crate::debug::DebugMode;
|
||||
use crate::edit::EditMode;
|
||||
use crate::game::{State, Transition};
|
||||
use crate::game::{State, Transition, WizardState};
|
||||
use crate::ui::{ShowEverything, UI};
|
||||
use ezgui::{
|
||||
hotkey, lctrl, EventCtx, EventLoopMode, GfxCtx, Key, ModalMenu, Text, Wizard, WrappedWizard,
|
||||
};
|
||||
use ezgui::{hotkey, lctrl, EventCtx, EventLoopMode, GfxCtx, Key, ModalMenu, Text, Wizard};
|
||||
use geom::Duration;
|
||||
use sim::Sim;
|
||||
|
||||
@ -175,10 +173,7 @@ impl State for SandboxMode {
|
||||
});
|
||||
}
|
||||
if self.menu.action("pick a savestate to load") {
|
||||
return Transition::Push(Box::new(LoadSavestate {
|
||||
path: ui.primary.sim.save_dir(),
|
||||
wizard: Wizard::new(),
|
||||
}));
|
||||
return Transition::Push(WizardState::new(Box::new(load_savestate)));
|
||||
}
|
||||
|
||||
if let Some(t) = time_controls(ctx, ui, &mut self.menu) {
|
||||
@ -213,41 +208,22 @@ impl State for SandboxMode {
|
||||
}
|
||||
}
|
||||
|
||||
struct LoadSavestate {
|
||||
path: String,
|
||||
wizard: Wizard,
|
||||
}
|
||||
fn load_savestate(wiz: &mut Wizard, ctx: &mut EventCtx, ui: &mut UI) -> Option<Transition> {
|
||||
let path = ui.primary.sim.save_dir();
|
||||
|
||||
impl State for LoadSavestate {
|
||||
fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI) -> Transition {
|
||||
if let Some(ss) = pick_savestate(&self.path, &mut self.wizard.wrap(ctx)) {
|
||||
ctx.loading_screen("load savestate", |ctx, mut timer| {
|
||||
ui.primary.sim = Sim::load_savestate(ss, &mut timer).unwrap();
|
||||
ui.recalculate_current_selection(ctx);
|
||||
});
|
||||
return Transition::Pop;
|
||||
} else if self.wizard.aborted() {
|
||||
return Transition::Pop;
|
||||
}
|
||||
Transition::Keep
|
||||
}
|
||||
let (ss, _) = wiz.wrap(ctx).choose_something_no_keys::<()>(
|
||||
"Load which savestate?",
|
||||
Box::new(move || {
|
||||
abstutil::list_dir(std::path::Path::new(&path))
|
||||
.into_iter()
|
||||
.map(|f| (f, ()))
|
||||
.collect()
|
||||
}),
|
||||
)?;
|
||||
|
||||
fn draw(&self, g: &mut GfxCtx, _: &UI) {
|
||||
self.wizard.draw(g);
|
||||
}
|
||||
}
|
||||
|
||||
fn pick_savestate(path: &str, wizard: &mut WrappedWizard) -> Option<String> {
|
||||
let path_copy = path.to_string();
|
||||
wizard
|
||||
.choose_something_no_keys::<()>(
|
||||
"Load which savestate?",
|
||||
Box::new(move || {
|
||||
abstutil::list_dir(std::path::Path::new(&path_copy))
|
||||
.into_iter()
|
||||
.map(|f| (f, ()))
|
||||
.collect()
|
||||
}),
|
||||
)
|
||||
.map(|(f, _)| f)
|
||||
ctx.loading_screen("load savestate", |ctx, mut timer| {
|
||||
ui.primary.sim = Sim::load_savestate(ss, &mut timer).expect("Can't load savestate");
|
||||
ui.recalculate_current_selection(ctx);
|
||||
});
|
||||
Some(Transition::Pop)
|
||||
}
|
||||
|
@ -1,12 +1,11 @@
|
||||
use crate::game::{State, Transition};
|
||||
use crate::game::{State, Transition, WizardState};
|
||||
use crate::ui::UI;
|
||||
use ezgui::{
|
||||
hotkey, EventCtx, GfxCtx, HorizontalAlignment, Key, ModalMenu, Text, VerticalAlignment, Wizard,
|
||||
WrappedWizard,
|
||||
};
|
||||
use geom::{Duration, DurationHistogram};
|
||||
use itertools::Itertools;
|
||||
use sim::{FinishedTrips, TripID, TripMode};
|
||||
use sim::{TripID, TripMode};
|
||||
|
||||
pub struct Scoreboard {
|
||||
menu: ModalMenu,
|
||||
@ -47,16 +46,13 @@ impl Scoreboard {
|
||||
}
|
||||
|
||||
impl State for Scoreboard {
|
||||
fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI) -> Transition {
|
||||
fn event(&mut self, ctx: &mut EventCtx, _: &mut UI) -> Transition {
|
||||
self.menu.handle_event(ctx, None);
|
||||
if self.menu.action("quit") {
|
||||
return Transition::Pop;
|
||||
}
|
||||
if self.menu.action("browse trips") {
|
||||
return Transition::Push(Box::new(BrowseTrips {
|
||||
trips: ui.primary.sim.get_finished_trips(),
|
||||
wizard: Wizard::new(),
|
||||
}));
|
||||
return Transition::Push(WizardState::new(Box::new(browse_trips)));
|
||||
}
|
||||
Transition::Keep
|
||||
}
|
||||
@ -70,42 +66,21 @@ impl State for Scoreboard {
|
||||
}
|
||||
}
|
||||
|
||||
struct BrowseTrips {
|
||||
trips: FinishedTrips,
|
||||
wizard: Wizard,
|
||||
}
|
||||
|
||||
impl State for BrowseTrips {
|
||||
fn event(&mut self, ctx: &mut EventCtx, _: &mut UI) -> Transition {
|
||||
if pick_trip(&self.trips, &mut self.wizard.wrap(ctx)).is_some() {
|
||||
// TODO show trip departure, where it started and ended
|
||||
return Transition::Pop;
|
||||
} else if self.wizard.aborted() {
|
||||
return Transition::Pop;
|
||||
}
|
||||
Transition::Keep
|
||||
}
|
||||
|
||||
fn draw(&self, g: &mut GfxCtx, _: &UI) {
|
||||
self.wizard.draw(g);
|
||||
}
|
||||
}
|
||||
|
||||
fn pick_trip(trips: &FinishedTrips, wizard: &mut WrappedWizard) -> Option<TripID> {
|
||||
let mode = wizard
|
||||
.choose_something_no_keys::<TripMode>(
|
||||
"Browse which trips?",
|
||||
Box::new(|| {
|
||||
vec![
|
||||
("walk".to_string(), TripMode::Walk),
|
||||
("bike".to_string(), TripMode::Bike),
|
||||
("transit".to_string(), TripMode::Transit),
|
||||
("drive".to_string(), TripMode::Drive),
|
||||
]
|
||||
}),
|
||||
)?
|
||||
.1;
|
||||
fn browse_trips(wiz: &mut Wizard, ctx: &mut EventCtx, ui: &mut UI) -> Option<Transition> {
|
||||
let mut wizard = wiz.wrap(ctx);
|
||||
let (_, mode) = wizard.choose_something_no_keys::<TripMode>(
|
||||
"Browse which trips?",
|
||||
Box::new(|| {
|
||||
vec![
|
||||
("walk".to_string(), TripMode::Walk),
|
||||
("bike".to_string(), TripMode::Bike),
|
||||
("transit".to_string(), TripMode::Transit),
|
||||
("drive".to_string(), TripMode::Drive),
|
||||
]
|
||||
}),
|
||||
)?;
|
||||
// TODO Ewwww. Can't do this inside choices_generator because trips isn't &'a static.
|
||||
let trips = ui.primary.sim.get_finished_trips();
|
||||
let mut filtered: Vec<&(TripID, TripMode, Duration)> = trips
|
||||
.finished_trips
|
||||
.iter()
|
||||
@ -118,10 +93,10 @@ fn pick_trip(trips: &FinishedTrips, wizard: &mut WrappedWizard) -> Option<TripID
|
||||
// TODO Show percentile for time
|
||||
.map(|(id, _, dt)| (format!("{} taking {}", id, dt), *id))
|
||||
.collect();
|
||||
wizard
|
||||
.choose_something_no_keys::<TripID>(
|
||||
"Examine which trip?",
|
||||
Box::new(move || choices.clone()),
|
||||
)
|
||||
.map(|(_, id)| id)
|
||||
wizard.choose_something_no_keys::<TripID>(
|
||||
"Examine which trip?",
|
||||
Box::new(move || choices.clone()),
|
||||
)?;
|
||||
// TODO show trip departure, where it started and ended
|
||||
Some(Transition::Pop)
|
||||
}
|
||||
|
@ -1,14 +1,13 @@
|
||||
use crate::common::CommonState;
|
||||
use crate::game::{State, Transition};
|
||||
use crate::game::{State, Transition, WizardState};
|
||||
use crate::helpers::ID;
|
||||
use crate::render::DrawOptions;
|
||||
use crate::ui::{ShowEverything, UI};
|
||||
use abstutil::Timer;
|
||||
use ezgui::{hotkey, EventCtx, GfxCtx, Key, ModalMenu, Wizard, WrappedWizard};
|
||||
use ezgui::{hotkey, EventCtx, GfxCtx, Key, ModalMenu, Wizard};
|
||||
use geom::{Duration, PolyLine};
|
||||
use map_model::{
|
||||
BuildingID, IntersectionID, IntersectionType, LaneType, Map, PathRequest, Position,
|
||||
LANE_THICKNESS,
|
||||
BuildingID, IntersectionID, IntersectionType, LaneType, PathRequest, Position, LANE_THICKNESS,
|
||||
};
|
||||
use rand::seq::SliceRandom;
|
||||
use rand::Rng;
|
||||
@ -94,9 +93,7 @@ impl AgentSpawner {
|
||||
}
|
||||
None => {
|
||||
if ui.primary.sim.is_empty() && sandbox_menu.action("start a scenario") {
|
||||
return Some(Box::new(InstantiateScenario {
|
||||
wizard: Wizard::new(),
|
||||
}));
|
||||
return Some(WizardState::new(Box::new(instantiate_scenario)));
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
@ -358,51 +355,17 @@ fn spawn_agents_around(i: IntersectionID, ui: &mut UI, ctx: &EventCtx) {
|
||||
ui.recalculate_current_selection(ctx);
|
||||
}
|
||||
|
||||
// TODO Dedupe with code from mission/mod.rs.
|
||||
struct InstantiateScenario {
|
||||
wizard: Wizard,
|
||||
}
|
||||
|
||||
impl State for InstantiateScenario {
|
||||
fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI) -> Transition {
|
||||
if let Some(scenario) = pick_scenario(
|
||||
ui.primary.current_flags.num_agents,
|
||||
&ui.primary.map,
|
||||
&mut self.wizard.wrap(ctx),
|
||||
) {
|
||||
ctx.loading_screen("instantiate scenario", |_, timer| {
|
||||
scenario.instantiate(
|
||||
&mut ui.primary.sim,
|
||||
&ui.primary.map,
|
||||
&mut ui.primary.current_flags.sim_flags.make_rng(),
|
||||
timer,
|
||||
);
|
||||
ui.primary.sim.step(&ui.primary.map, SMALL_DT);
|
||||
});
|
||||
return Transition::Pop;
|
||||
} else if self.wizard.aborted() {
|
||||
return Transition::Pop;
|
||||
}
|
||||
Transition::Keep
|
||||
}
|
||||
|
||||
fn draw(&self, g: &mut GfxCtx, _: &UI) {
|
||||
self.wizard.draw(g);
|
||||
}
|
||||
}
|
||||
|
||||
fn pick_scenario(
|
||||
num_agents: Option<usize>,
|
||||
map: &Map,
|
||||
wizard: &mut WrappedWizard,
|
||||
) -> Option<Scenario> {
|
||||
fn instantiate_scenario(wiz: &mut Wizard, ctx: &mut EventCtx, ui: &mut UI) -> Option<Transition> {
|
||||
let num_agents = ui.primary.current_flags.num_agents;
|
||||
let builtin = if let Some(n) = num_agents {
|
||||
format!("random scenario with {} agents", n)
|
||||
} else {
|
||||
"random scenario with some agents".to_string()
|
||||
};
|
||||
let map = &ui.primary.map;
|
||||
let map_name = map.get_name().to_string();
|
||||
let (_, scenario_name) = wizard.choose_something_no_keys::<String>(
|
||||
|
||||
let (_, scenario_name) = wiz.wrap(ctx).choose_something_no_keys::<String>(
|
||||
"Instantiate which scenario?",
|
||||
Box::new(move || {
|
||||
let mut list = vec![
|
||||
@ -413,7 +376,8 @@ fn pick_scenario(
|
||||
list
|
||||
}),
|
||||
)?;
|
||||
Some(if scenario_name == "builtin" {
|
||||
|
||||
let scenario = if scenario_name == "builtin" {
|
||||
if let Some(n) = num_agents {
|
||||
Scenario::scaled_run(map, n)
|
||||
} else {
|
||||
@ -427,5 +391,15 @@ fn pick_scenario(
|
||||
&mut Timer::throwaway(),
|
||||
)
|
||||
.unwrap()
|
||||
})
|
||||
};
|
||||
ctx.loading_screen("instantiate scenario", |_, timer| {
|
||||
scenario.instantiate(
|
||||
&mut ui.primary.sim,
|
||||
&ui.primary.map,
|
||||
&mut ui.primary.current_flags.sim_flags.make_rng(),
|
||||
timer,
|
||||
);
|
||||
ui.primary.sim.step(&ui.primary.map, SMALL_DT);
|
||||
});
|
||||
Some(Transition::Pop)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user