mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-27 16:36:02 +03:00
collapsing load/create scenario options directly into mission mode
This commit is contained in:
parent
a6aa46dd61
commit
a7b10b7ec5
@ -11,8 +11,11 @@ use crate::render::DrawOptions;
|
|||||||
use crate::sandbox::SandboxMode;
|
use crate::sandbox::SandboxMode;
|
||||||
use crate::ui::ShowEverything;
|
use crate::ui::ShowEverything;
|
||||||
use crate::ui::UI;
|
use crate::ui::UI;
|
||||||
|
use abstutil::Timer;
|
||||||
use ezgui::{hotkey, EventCtx, EventLoopMode, GfxCtx, Key, ModalMenu, Wizard, WrappedWizard};
|
use ezgui::{hotkey, EventCtx, EventLoopMode, GfxCtx, Key, ModalMenu, Wizard, WrappedWizard};
|
||||||
use geom::Duration;
|
use geom::Duration;
|
||||||
|
use map_model::Map;
|
||||||
|
use sim::Scenario;
|
||||||
|
|
||||||
pub struct MissionEditMode {
|
pub struct MissionEditMode {
|
||||||
state: State,
|
state: State,
|
||||||
@ -21,7 +24,9 @@ pub struct MissionEditMode {
|
|||||||
enum State {
|
enum State {
|
||||||
Exploring(ModalMenu),
|
Exploring(ModalMenu),
|
||||||
Neighborhood(neighborhood::NeighborhoodEditor),
|
Neighborhood(neighborhood::NeighborhoodEditor),
|
||||||
Scenario(scenario::ScenarioEditor),
|
LoadScenario(Wizard),
|
||||||
|
CreateNewScenario(Wizard),
|
||||||
|
EditScenario(scenario::ScenarioEditor),
|
||||||
DataViz(dataviz::DataVisualizer),
|
DataViz(dataviz::DataVisualizer),
|
||||||
IndividualTrips(individ_trips::TripsVisualizer),
|
IndividualTrips(individ_trips::TripsVisualizer),
|
||||||
AllTrips(all_trips::TripsVisualizer),
|
AllTrips(all_trips::TripsVisualizer),
|
||||||
@ -44,7 +49,8 @@ impl MissionEditMode {
|
|||||||
(hotkey(Key::S), "set up simulation with PSRC trips"),
|
(hotkey(Key::S), "set up simulation with PSRC trips"),
|
||||||
(hotkey(Key::Q), "create scenario from PSRC trips"),
|
(hotkey(Key::Q), "create scenario from PSRC trips"),
|
||||||
(hotkey(Key::N), "manage neighborhoods"),
|
(hotkey(Key::N), "manage neighborhoods"),
|
||||||
(hotkey(Key::W), "manage scenarios"),
|
(hotkey(Key::W), "load scenario"),
|
||||||
|
(None, "create new scenario"),
|
||||||
],
|
],
|
||||||
ctx,
|
ctx,
|
||||||
)),
|
)),
|
||||||
@ -98,10 +104,10 @@ impl MissionEditMode {
|
|||||||
mode.state = State::Neighborhood(
|
mode.state = State::Neighborhood(
|
||||||
neighborhood::NeighborhoodEditor::PickNeighborhood(Wizard::new()),
|
neighborhood::NeighborhoodEditor::PickNeighborhood(Wizard::new()),
|
||||||
);
|
);
|
||||||
} else if menu.action("manage scenarios") {
|
} else if menu.action("load scenario") {
|
||||||
mode.state = State::Scenario(scenario::ScenarioEditor::PickScenario(
|
mode.state = State::LoadScenario(Wizard::new());
|
||||||
Wizard::new(),
|
} else if menu.action("create new scenario") {
|
||||||
));
|
mode.state = State::CreateNewScenario(Wizard::new());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
State::DataViz(ref mut viz) => {
|
State::DataViz(ref mut viz) => {
|
||||||
@ -134,7 +140,35 @@ impl MissionEditMode {
|
|||||||
mode.state = MissionEditMode::new(ctx, &mut state.ui).state;
|
mode.state = MissionEditMode::new(ctx, &mut state.ui).state;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
State::Scenario(ref mut editor) => {
|
State::LoadScenario(ref mut wizard) => {
|
||||||
|
if let Some(scenario) =
|
||||||
|
load_scenario(&state.ui.primary.map, &mut wizard.wrap(ctx))
|
||||||
|
{
|
||||||
|
mode.state =
|
||||||
|
State::EditScenario(scenario::ScenarioEditor::new(scenario, ctx));
|
||||||
|
} else if wizard.aborted() {
|
||||||
|
mode.state = MissionEditMode::new(ctx, &mut state.ui).state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
State::CreateNewScenario(ref mut wizard) => {
|
||||||
|
let mut wrapped = wizard.wrap(ctx);
|
||||||
|
if let Some(name) = wrapped.input_string("Name the scenario") {
|
||||||
|
mode.state = State::EditScenario(scenario::ScenarioEditor::new(
|
||||||
|
Scenario {
|
||||||
|
scenario_name: name,
|
||||||
|
map_name: state.ui.primary.map.get_name().to_string(),
|
||||||
|
seed_parked_cars: Vec::new(),
|
||||||
|
spawn_over_time: Vec::new(),
|
||||||
|
border_spawn_over_time: Vec::new(),
|
||||||
|
individ_trips: Vec::new(),
|
||||||
|
},
|
||||||
|
ctx,
|
||||||
|
));
|
||||||
|
} else if wizard.aborted() {
|
||||||
|
mode.state = MissionEditMode::new(ctx, &mut state.ui).state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
State::EditScenario(ref mut editor) => {
|
||||||
if let Some(new_mode) = editor.event(ctx, &mut state.ui) {
|
if let Some(new_mode) = editor.event(ctx, &mut state.ui) {
|
||||||
state.mode = new_mode;
|
state.mode = new_mode;
|
||||||
}
|
}
|
||||||
@ -174,9 +208,12 @@ impl MissionEditMode {
|
|||||||
State::Neighborhood(ref editor) => {
|
State::Neighborhood(ref editor) => {
|
||||||
editor.draw(g, &state.ui);
|
editor.draw(g, &state.ui);
|
||||||
}
|
}
|
||||||
State::Scenario(ref editor) => {
|
State::EditScenario(ref editor) => {
|
||||||
editor.draw(g, &state.ui);
|
editor.draw(g, &state.ui);
|
||||||
}
|
}
|
||||||
|
State::LoadScenario(ref wizard) | State::CreateNewScenario(ref wizard) => {
|
||||||
|
wizard.draw(g);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
@ -186,3 +223,19 @@ impl MissionEditMode {
|
|||||||
pub fn input_time(wizard: &mut WrappedWizard, query: &str) -> Option<Duration> {
|
pub fn input_time(wizard: &mut WrappedWizard, query: &str) -> Option<Duration> {
|
||||||
wizard.input_something(query, None, Box::new(|line| Duration::parse(&line)))
|
wizard.input_something(query, None, Box::new(|line| Duration::parse(&line)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn load_scenario(map: &Map, wizard: &mut WrappedWizard) -> Option<Scenario> {
|
||||||
|
let map_name = map.get_name().to_string();
|
||||||
|
wizard
|
||||||
|
.choose_something_no_keys::<String>(
|
||||||
|
"Load which scenario?",
|
||||||
|
Box::new(move || abstutil::list_all_objects("scenarios", &map_name)),
|
||||||
|
)
|
||||||
|
.map(|(_, s)| {
|
||||||
|
abstutil::read_binary(
|
||||||
|
&format!("../data/scenarios/{}/{}.bin", map.get_name(), s),
|
||||||
|
&mut Timer::throwaway(),
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
@ -2,47 +2,38 @@ use crate::game::Mode;
|
|||||||
use crate::mission::{input_time, MissionEditMode};
|
use crate::mission::{input_time, MissionEditMode};
|
||||||
use crate::sandbox::SandboxMode;
|
use crate::sandbox::SandboxMode;
|
||||||
use crate::ui::UI;
|
use crate::ui::UI;
|
||||||
use abstutil::{Timer, WeightedUsizeChoice};
|
use abstutil::WeightedUsizeChoice;
|
||||||
use ezgui::{hotkey, EventCtx, GfxCtx, Key, LogScroller, ModalMenu, Wizard, WrappedWizard};
|
use ezgui::{hotkey, EventCtx, GfxCtx, Key, LogScroller, ModalMenu, Wizard, WrappedWizard};
|
||||||
use geom::Duration;
|
use geom::Duration;
|
||||||
use map_model::{IntersectionID, Map, Neighborhood};
|
use map_model::{IntersectionID, Map, Neighborhood};
|
||||||
use sim::{BorderSpawnOverTime, OriginDestination, Scenario, SeedParkedCars, SpawnOverTime};
|
use sim::{BorderSpawnOverTime, OriginDestination, Scenario, SeedParkedCars, SpawnOverTime};
|
||||||
|
|
||||||
pub enum ScenarioEditor {
|
pub enum ScenarioEditor {
|
||||||
PickScenario(Wizard),
|
|
||||||
ManageScenario(ModalMenu, Scenario, LogScroller),
|
ManageScenario(ModalMenu, Scenario, LogScroller),
|
||||||
EditScenario(Scenario, Wizard),
|
EditScenario(Scenario, Wizard),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ScenarioEditor {
|
impl ScenarioEditor {
|
||||||
fn modal_menu(name: &str, ctx: &EventCtx) -> ModalMenu {
|
pub fn new(scenario: Scenario, ctx: &mut EventCtx) -> ScenarioEditor {
|
||||||
ModalMenu::new(
|
let scroller = LogScroller::new(scenario.scenario_name.clone(), scenario.describe());
|
||||||
&format!("Scenario Editor for {}", name),
|
ScenarioEditor::ManageScenario(
|
||||||
vec![
|
ModalMenu::new(
|
||||||
(hotkey(Key::Escape), "quit"),
|
&format!("Scenario Editor for {}", scenario.scenario_name),
|
||||||
(hotkey(Key::S), "save"),
|
vec![
|
||||||
(hotkey(Key::E), "edit"),
|
(hotkey(Key::Escape), "quit"),
|
||||||
(hotkey(Key::I), "instantiate"),
|
(hotkey(Key::S), "save"),
|
||||||
],
|
(hotkey(Key::E), "edit"),
|
||||||
ctx,
|
(hotkey(Key::I), "instantiate"),
|
||||||
|
],
|
||||||
|
ctx,
|
||||||
|
),
|
||||||
|
scenario,
|
||||||
|
scroller,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI) -> Option<Mode> {
|
pub fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI) -> Option<Mode> {
|
||||||
match self {
|
match self {
|
||||||
ScenarioEditor::PickScenario(ref mut wizard) => {
|
|
||||||
if let Some(scenario) = pick_scenario(&ui.primary.map, wizard.wrap(ctx)) {
|
|
||||||
let scroller =
|
|
||||||
LogScroller::new(scenario.scenario_name.clone(), scenario.describe());
|
|
||||||
*self = ScenarioEditor::ManageScenario(
|
|
||||||
ScenarioEditor::modal_menu(&scenario.scenario_name, ctx),
|
|
||||||
scenario,
|
|
||||||
scroller,
|
|
||||||
);
|
|
||||||
} else if wizard.aborted() {
|
|
||||||
return Some(Mode::Mission(MissionEditMode::new(ctx, ui)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ScenarioEditor::ManageScenario(ref mut menu, scenario, ref mut scroller) => {
|
ScenarioEditor::ManageScenario(ref mut menu, scenario, ref mut scroller) => {
|
||||||
menu.handle_event(ctx, None);
|
menu.handle_event(ctx, None);
|
||||||
ctx.canvas.handle_event(ctx.input);
|
ctx.canvas.handle_event(ctx.input);
|
||||||
@ -67,22 +58,10 @@ impl ScenarioEditor {
|
|||||||
}
|
}
|
||||||
ScenarioEditor::EditScenario(ref mut scenario, ref mut wizard) => {
|
ScenarioEditor::EditScenario(ref mut scenario, ref mut wizard) => {
|
||||||
if let Some(()) = edit_scenario(&ui.primary.map, scenario, wizard.wrap(ctx)) {
|
if let Some(()) = edit_scenario(&ui.primary.map, scenario, wizard.wrap(ctx)) {
|
||||||
let scroller =
|
|
||||||
LogScroller::new(scenario.scenario_name.clone(), scenario.describe());
|
|
||||||
// TODO autosave, or at least make it clear there are unsaved edits
|
// TODO autosave, or at least make it clear there are unsaved edits
|
||||||
*self = ScenarioEditor::ManageScenario(
|
*self = ScenarioEditor::new(scenario.clone(), ctx);
|
||||||
ScenarioEditor::modal_menu(&scenario.scenario_name, ctx),
|
|
||||||
scenario.clone(),
|
|
||||||
scroller,
|
|
||||||
);
|
|
||||||
} else if wizard.aborted() {
|
} else if wizard.aborted() {
|
||||||
let scroller =
|
*self = ScenarioEditor::new(scenario.clone(), ctx);
|
||||||
LogScroller::new(scenario.scenario_name.clone(), scenario.describe());
|
|
||||||
*self = ScenarioEditor::ManageScenario(
|
|
||||||
ScenarioEditor::modal_menu(&scenario.scenario_name, ctx),
|
|
||||||
scenario.clone(),
|
|
||||||
scroller,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -91,9 +70,6 @@ impl ScenarioEditor {
|
|||||||
|
|
||||||
pub fn draw(&self, g: &mut GfxCtx, ui: &UI) {
|
pub fn draw(&self, g: &mut GfxCtx, ui: &UI) {
|
||||||
match self {
|
match self {
|
||||||
ScenarioEditor::PickScenario(wizard) => {
|
|
||||||
wizard.draw(g);
|
|
||||||
}
|
|
||||||
ScenarioEditor::ManageScenario(ref menu, _, scroller) => {
|
ScenarioEditor::ManageScenario(ref menu, _, scroller) => {
|
||||||
scroller.draw(g);
|
scroller.draw(g);
|
||||||
menu.draw(g);
|
menu.draw(g);
|
||||||
@ -108,26 +84,6 @@ impl ScenarioEditor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pick_scenario(map: &Map, mut wizard: WrappedWizard) -> Option<Scenario> {
|
|
||||||
let load_existing = "Load existing scenario";
|
|
||||||
let create_new = "Create new scenario";
|
|
||||||
if wizard.choose_string("What scenario to edit?", vec![load_existing, create_new])?
|
|
||||||
== load_existing
|
|
||||||
{
|
|
||||||
load_scenario(map, &mut wizard, "Load which scenario?")
|
|
||||||
} else {
|
|
||||||
let scenario_name = wizard.input_string("Name the scenario")?;
|
|
||||||
Some(Scenario {
|
|
||||||
scenario_name,
|
|
||||||
map_name: map.get_name().to_string(),
|
|
||||||
seed_parked_cars: Vec::new(),
|
|
||||||
spawn_over_time: Vec::new(),
|
|
||||||
border_spawn_over_time: Vec::new(),
|
|
||||||
individ_trips: Vec::new(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn edit_scenario(map: &Map, scenario: &mut Scenario, mut wizard: WrappedWizard) -> Option<()> {
|
fn edit_scenario(map: &Map, scenario: &mut Scenario, mut wizard: WrappedWizard) -> Option<()> {
|
||||||
let seed_parked = "Seed parked cars";
|
let seed_parked = "Seed parked cars";
|
||||||
let spawn = "Spawn agents";
|
let spawn = "Spawn agents";
|
||||||
@ -224,22 +180,6 @@ fn choose_neighborhood(map: &Map, wizard: &mut WrappedWizard, query: &str) -> Op
|
|||||||
.map(|(n, _)| n)
|
.map(|(n, _)| n)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_scenario(map: &Map, wizard: &mut WrappedWizard, query: &str) -> Option<Scenario> {
|
|
||||||
let map_name = map.get_name().to_string();
|
|
||||||
wizard
|
|
||||||
.choose_something_no_keys::<String>(
|
|
||||||
query,
|
|
||||||
Box::new(move || abstutil::list_all_objects("scenarios", &map_name)),
|
|
||||||
)
|
|
||||||
.map(|(_, s)| {
|
|
||||||
abstutil::read_binary(
|
|
||||||
&format!("../data/scenarios/{}/{}.bin", map.get_name(), s),
|
|
||||||
&mut Timer::throwaway(),
|
|
||||||
)
|
|
||||||
.unwrap()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn input_weighted_usize(wizard: &mut WrappedWizard, query: &str) -> Option<WeightedUsizeChoice> {
|
fn input_weighted_usize(wizard: &mut WrappedWizard, query: &str) -> Option<WeightedUsizeChoice> {
|
||||||
wizard.input_something(
|
wizard.input_something(
|
||||||
query,
|
query,
|
||||||
|
Loading…
Reference in New Issue
Block a user