refactoring wizards and loading/listing stuff

This commit is contained in:
Dustin Carlino 2018-10-08 11:57:23 -07:00
parent f1503c2de1
commit 23fc634eb4
6 changed files with 84 additions and 73 deletions

View File

@ -103,8 +103,9 @@ pub fn deserialize_multimap<
} }
// Just list all things from a directory, return sorted by name, with file extension removed. // Just list all things from a directory, return sorted by name, with file extension removed.
pub fn list_all_objects(dir: &str, map_name: &str) -> Vec<String> { // Pretty hacky that we return a (String, String).
let mut results: BTreeSet<String> = BTreeSet::new(); pub fn list_all_objects(dir: &str, map_name: &str) -> Vec<(String, String)> {
let mut results: BTreeSet<(String, String)> = BTreeSet::new();
match std::fs::read_dir(format!("../data/{}/{}/", dir, map_name)) { match std::fs::read_dir(format!("../data/{}/{}/", dir, map_name)) {
Ok(iter) => { Ok(iter) => {
for entry in iter { for entry in iter {
@ -114,7 +115,7 @@ pub fn list_all_objects(dir: &str, map_name: &str) -> Vec<String> {
.to_os_string() .to_os_string()
.into_string() .into_string()
.unwrap(); .unwrap();
results.insert(name); results.insert((name.clone(), name));
} }
} }
Err(ref e) if e.kind() == ErrorKind::NotFound => {} Err(ref e) if e.kind() == ErrorKind::NotFound => {}

View File

@ -1,10 +1,9 @@
use abstutil;
use ezgui::{Canvas, GfxCtx, LogScroller, UserInput, Wizard, WrappedWizard}; use ezgui::{Canvas, GfxCtx, LogScroller, UserInput, Wizard, WrappedWizard};
use map_model::Map; use map_model::Map;
use objects::SIM_SETUP; use objects::SIM_SETUP;
use piston::input::Key; use piston::input::Key;
use plugins::Colorizer; use plugins::{choose_edits, choose_scenario, load_ab_test, Colorizer};
use sim::{ABTest, MapEdits, Scenario}; use sim::ABTest;
pub enum ABTestManager { pub enum ABTestManager {
Inactive, Inactive,
@ -70,12 +69,7 @@ fn pick_ab_test(map: &Map, mut wizard: WrappedWizard) -> Option<ABTest> {
if wizard.choose_string("What A/B test to manage?", vec![load_existing, create_new])? if wizard.choose_string("What A/B test to manage?", vec![load_existing, create_new])?
== load_existing == load_existing
{ {
let map_name = map.get_name().to_string(); load_ab_test(map, &mut wizard, "Load which A/B test?")
wizard
.choose_something::<ABTest>(
"Load which A/B test?",
Box::new(move || abstutil::load_all_objects("ab_tests", &map_name)),
).map(|(_, t)| t)
} else { } else {
let test_name = wizard.input_string("Name the A/B test")?; let test_name = wizard.input_string("Name the A/B test")?;
let ab_test = ABTest { let ab_test = ABTest {
@ -89,25 +83,3 @@ fn pick_ab_test(map: &Map, mut wizard: WrappedWizard) -> Option<ABTest> {
Some(ab_test) Some(ab_test)
} }
} }
// TODO it'd be neat to instead register parsers and choice generators on a wizard, then call them?
// these file-loading ones are especially boilerplate. maybe even just refactor that in the editor
// crate.
fn choose_scenario(map: &Map, wizard: &mut WrappedWizard, query: &str) -> Option<String> {
let map_name = map.get_name().to_string();
wizard
.choose_something::<Scenario>(
query,
Box::new(move || abstutil::load_all_objects("scenarios", &map_name)),
).map(|(n, _)| n)
}
fn choose_edits(map: &Map, wizard: &mut WrappedWizard, query: &str) -> Option<String> {
let map_name = map.get_name().to_string();
wizard
.choose_something::<MapEdits>(
query,
Box::new(move || abstutil::load_all_objects("edits", &map_name)),
).map(|(n, _)| n)
}

View File

@ -1,10 +1,9 @@
use abstutil;
use ezgui::{Canvas, GfxCtx, Text, UserInput, Wizard, WrappedWizard}; use ezgui::{Canvas, GfxCtx, Text, UserInput, Wizard, WrappedWizard};
use geom::{Circle, Line, Polygon}; use geom::{Circle, Line, Polygon};
use map_model::Map; use map_model::Map;
use objects::EDIT_MAP; use objects::EDIT_MAP;
use piston::input::Key; use piston::input::Key;
use plugins::Colorizer; use plugins::{load_neighborhood, Colorizer};
use sim::Neighborhood; use sim::Neighborhood;
const POINT_RADIUS: f64 = 2.0; const POINT_RADIUS: f64 = 2.0;
@ -148,12 +147,7 @@ fn pick_neighborhood(map: &Map, mut wizard: WrappedWizard) -> Option<Neighborhoo
vec![load_existing, create_new], vec![load_existing, create_new],
)? == load_existing )? == load_existing
{ {
let map_name = map.get_name().to_string(); load_neighborhood(map, &mut wizard, "Load which neighborhood?")
wizard
.choose_something::<Neighborhood>(
"Load which neighborhood?",
Box::new(move || abstutil::load_all_objects("neighborhoods", &map_name)),
).map(|(_, n)| n)
} else { } else {
let name = wizard.input_string("Name the neighborhood")?; let name = wizard.input_string("Name the neighborhood")?;
Some(Neighborhood { Some(Neighborhood {

View File

@ -1,11 +1,10 @@
use abstutil;
use control::ControlMap; use control::ControlMap;
use ezgui::{Canvas, GfxCtx, UserInput, Wizard, WrappedWizard}; use ezgui::{Canvas, GfxCtx, UserInput, Wizard, WrappedWizard};
use map_model::Map; use map_model::Map;
use objects::SIM_SETUP; use objects::SIM_SETUP;
use piston::input::Key; use piston::input::Key;
use plugins::road_editor::RoadEditor; use plugins::road_editor::RoadEditor;
use plugins::Colorizer; use plugins::{choose_edits, Colorizer};
use sim::{MapEdits, SimFlags}; use sim::{MapEdits, SimFlags};
pub struct EditsManager { pub struct EditsManager {
@ -123,10 +122,7 @@ fn manage_edits(
Some(()) Some(())
} }
x if x == load => { x if x == load => {
let map_name = map.get_name().to_string(); let load_name = choose_edits(map, &mut wizard, "Load which map edits?")?;
let edits = abstutil::list_all_objects("edits", &map_name);
let edit_refs = edits.iter().map(|s| s.as_str()).collect();
let load_name = wizard.choose_string("Load which map edits?", edit_refs)?;
let mut flags = current_flags.clone(); let mut flags = current_flags.clone();
flags.edits_name = load_name; flags.edits_name = load_name;
*new_flags = Some(flags); *new_flags = Some(flags);

View File

@ -20,11 +20,80 @@ pub mod traffic_signal_editor;
pub mod turn_cycler; pub mod turn_cycler;
pub mod warp; pub mod warp;
use ezgui::Color; use abstutil;
use ezgui::{Color, WrappedWizard};
use map_model::Map;
use objects::{Ctx, ID}; use objects::{Ctx, ID};
use sim::{ABTest, Neighborhood, Scenario, Tick};
pub trait Colorizer { pub trait Colorizer {
fn color_for(&self, _obj: ID, _ctx: Ctx) -> Option<Color> { fn color_for(&self, _obj: ID, _ctx: Ctx) -> Option<Color> {
None None
} }
} }
// TODO Further refactoring should be done, but at least group these here to start.
// General principles are to avoid actually deserializing the objects unless needed.
pub fn choose_neighborhood(map: &Map, wizard: &mut WrappedWizard, query: &str) -> Option<String> {
let map_name = map.get_name().to_string();
// Load the full object, since various plugins visualize the neighborhood when menuing over it
wizard
.choose_something::<Neighborhood>(
query,
Box::new(move || abstutil::load_all_objects("neighborhoods", &map_name)),
).map(|(n, _)| n)
}
pub fn load_neighborhood(
map: &Map,
wizard: &mut WrappedWizard,
query: &str,
) -> Option<Neighborhood> {
let map_name = map.get_name().to_string();
wizard
.choose_something::<Neighborhood>(
query,
Box::new(move || abstutil::load_all_objects("neighborhoods", &map_name)),
).map(|(_, n)| n)
}
pub fn load_scenario(map: &Map, wizard: &mut WrappedWizard, query: &str) -> Option<Scenario> {
let map_name = map.get_name().to_string();
wizard
.choose_something::<Scenario>(
query,
Box::new(move || abstutil::load_all_objects("scenarios", &map_name)),
).map(|(_, s)| s)
}
pub fn choose_scenario(map: &Map, wizard: &mut WrappedWizard, query: &str) -> Option<String> {
let map_name = map.get_name().to_string();
wizard
.choose_something::<String>(
query,
Box::new(move || abstutil::list_all_objects("scenarios", &map_name)),
).map(|(n, _)| n)
}
pub fn choose_edits(map: &Map, wizard: &mut WrappedWizard, query: &str) -> Option<String> {
let map_name = map.get_name().to_string();
wizard
.choose_something::<String>(
query,
Box::new(move || abstutil::list_all_objects("edits", &map_name)),
).map(|(n, _)| n)
}
pub fn load_ab_test(map: &Map, wizard: &mut WrappedWizard, query: &str) -> Option<ABTest> {
let map_name = map.get_name().to_string();
wizard
.choose_something::<ABTest>(
query,
Box::new(move || abstutil::load_all_objects("ab_tests", &map_name)),
).map(|(_, t)| t)
}
pub fn input_tick(wizard: &mut WrappedWizard, query: &str) -> Option<Tick> {
wizard.input_something(query, Box::new(|line| Tick::parse(&line)))
}

View File

@ -1,11 +1,10 @@
use abstutil;
use ezgui::{Canvas, GfxCtx, LogScroller, UserInput, Wizard, WrappedWizard}; use ezgui::{Canvas, GfxCtx, LogScroller, UserInput, Wizard, WrappedWizard};
use geom::Polygon; use geom::Polygon;
use map_model::Map; use map_model::Map;
use objects::SIM_SETUP; use objects::SIM_SETUP;
use piston::input::Key; use piston::input::Key;
use plugins::Colorizer; use plugins::{choose_neighborhood, input_tick, load_scenario, Colorizer};
use sim::{Neighborhood, Scenario, SeedParkedCars, Sim, SpawnOverTime, Tick}; use sim::{Neighborhood, Scenario, SeedParkedCars, Sim, SpawnOverTime};
pub enum ScenarioManager { pub enum ScenarioManager {
Inactive, Inactive,
@ -99,12 +98,7 @@ fn pick_scenario(map: &Map, mut wizard: WrappedWizard) -> Option<Scenario> {
if wizard.choose_string("What scenario to edit?", vec![load_existing, create_new])? if wizard.choose_string("What scenario to edit?", vec![load_existing, create_new])?
== load_existing == load_existing
{ {
let map_name = map.get_name().to_string(); load_scenario(map, &mut wizard, "Load which scenario?")
wizard
.choose_something::<Scenario>(
"Load which scenario?",
Box::new(move || abstutil::load_all_objects("scenarios", &map_name)),
).map(|(_, s)| s)
} else { } else {
let scenario_name = wizard.input_string("Name the scenario")?; let scenario_name = wizard.input_string("Name the scenario")?;
Some(Scenario { Some(Scenario {
@ -146,18 +140,3 @@ fn edit_scenario(map: &Map, scenario: &mut Scenario, mut wizard: WrappedWizard)
Some(()) Some(())
} }
} }
// TODO it'd be neat to instead register parsers and choice generators on a wizard, then call them?
fn choose_neighborhood(map: &Map, wizard: &mut WrappedWizard, query: &str) -> Option<String> {
let map_name = map.get_name().to_string();
wizard
.choose_something::<Neighborhood>(
query,
Box::new(move || abstutil::load_all_objects("neighborhoods", &map_name)),
).map(|(n, _)| n)
}
fn input_tick(wizard: &mut WrappedWizard, query: &str) -> Option<Tick> {
wizard.input_something(query, Box::new(|line| Tick::parse(&line)))
}