mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-28 12:12:00 +03:00
Slightly simplify some plumbing of variables through nested closures, by
remembering that FnOnce exists
This commit is contained in:
parent
5ef48a5d1c
commit
81dae1e39c
@ -15,14 +15,15 @@ pub struct CityPicker {
|
||||
// In untranslated screen-space
|
||||
regions: Vec<(String, Color, Polygon)>,
|
||||
selected: Option<usize>,
|
||||
on_load: Box<dyn Fn(&mut EventCtx, &mut App) -> Transition>,
|
||||
// Wrapped in an Option just to make calling from event() work.
|
||||
on_load: Option<Box<dyn FnOnce(&mut EventCtx, &mut App) -> Transition>>,
|
||||
}
|
||||
|
||||
impl CityPicker {
|
||||
pub fn new(
|
||||
ctx: &mut EventCtx,
|
||||
app: &mut App,
|
||||
on_load: Box<dyn Fn(&mut EventCtx, &mut App) -> Transition>,
|
||||
on_load: Box<dyn FnOnce(&mut EventCtx, &mut App) -> Transition>,
|
||||
) -> Box<dyn State> {
|
||||
app.primary.current_selection = None;
|
||||
|
||||
@ -81,7 +82,7 @@ impl CityPicker {
|
||||
Box::new(CityPicker {
|
||||
regions,
|
||||
selected: None,
|
||||
on_load,
|
||||
on_load: Some(on_load),
|
||||
panel: Panel::new(
|
||||
Widget::col(vec![
|
||||
Widget::row(vec![
|
||||
@ -111,13 +112,11 @@ impl State for CityPicker {
|
||||
return Transition::Pop;
|
||||
}
|
||||
name => {
|
||||
let on_load =
|
||||
std::mem::replace(&mut self.on_load, Box::new(|_, _| Transition::Keep));
|
||||
return Transition::Replace(MapLoader::new(
|
||||
ctx,
|
||||
app,
|
||||
name.to_string(),
|
||||
on_load,
|
||||
self.on_load.take().unwrap(),
|
||||
));
|
||||
}
|
||||
},
|
||||
@ -152,9 +151,12 @@ impl State for CityPicker {
|
||||
.per_obj
|
||||
.left_click(ctx, format!("switch to {}", nice_map_name(name)))
|
||||
{
|
||||
let on_load =
|
||||
std::mem::replace(&mut self.on_load, Box::new(|_, _| Transition::Keep));
|
||||
return Transition::Replace(MapLoader::new(ctx, app, name.to_string(), on_load));
|
||||
return Transition::Replace(MapLoader::new(
|
||||
ctx,
|
||||
app,
|
||||
name.to_string(),
|
||||
self.on_load.take().unwrap(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -743,7 +743,7 @@ impl ScreenshotTest {
|
||||
todo_maps.pop().unwrap().to_string(),
|
||||
Box::new(move |_, _| {
|
||||
Transition::Replace(Box::new(ScreenshotTest {
|
||||
todo_maps: todo_maps.clone(),
|
||||
todo_maps,
|
||||
screenshot_done: false,
|
||||
}))
|
||||
}),
|
||||
|
@ -101,7 +101,6 @@ impl EditMode {
|
||||
app.primary.sim.handle_live_edits(&app.primary.map);
|
||||
Transition::Pop
|
||||
} else {
|
||||
let resume_time = old_sim.time();
|
||||
Transition::Multi(vec![
|
||||
Transition::Pop,
|
||||
Transition::Replace(SandboxMode::async_new(
|
||||
@ -112,7 +111,7 @@ impl EditMode {
|
||||
vec![Transition::Push(TimeWarpScreen::new(
|
||||
ctx,
|
||||
app,
|
||||
resume_time,
|
||||
old_sim.time(),
|
||||
None,
|
||||
))]
|
||||
}),
|
||||
|
@ -22,10 +22,12 @@ impl MapLoader {
|
||||
ctx: &mut EventCtx,
|
||||
app: &App,
|
||||
name: String,
|
||||
on_load: Box<dyn Fn(&mut EventCtx, &mut App) -> Transition>,
|
||||
on_load: Box<dyn FnOnce(&mut EventCtx, &mut App) -> Transition>,
|
||||
) -> Box<dyn State> {
|
||||
if app.primary.map.get_name() == &name {
|
||||
return Box::new(MapAlreadyLoaded { on_load });
|
||||
return Box::new(MapAlreadyLoaded {
|
||||
on_load: Some(on_load),
|
||||
});
|
||||
}
|
||||
|
||||
// TODO If we want to load montlake on the web, just pull from bundled data.
|
||||
@ -66,11 +68,11 @@ impl MapLoader {
|
||||
}
|
||||
|
||||
struct MapAlreadyLoaded {
|
||||
on_load: Box<dyn Fn(&mut EventCtx, &mut App) -> Transition>,
|
||||
on_load: Option<Box<dyn FnOnce(&mut EventCtx, &mut App) -> Transition>>,
|
||||
}
|
||||
impl State for MapAlreadyLoaded {
|
||||
fn event(&mut self, ctx: &mut EventCtx, app: &mut App) -> Transition {
|
||||
(self.on_load)(ctx, app)
|
||||
(self.on_load.take().unwrap())(ctx, app)
|
||||
}
|
||||
fn draw(&self, _: &mut GfxCtx, _: &App) {}
|
||||
}
|
||||
@ -81,16 +83,21 @@ mod native_loader {
|
||||
|
||||
pub struct FileLoader<T> {
|
||||
path: String,
|
||||
on_load: Box<dyn Fn(&mut EventCtx, &mut App, Option<T>) -> Transition>,
|
||||
// Wrapped in an Option just to make calling from event() work. Technically this is unsafe
|
||||
// if a caller fails to pop the FileLoader state in their transitions!
|
||||
on_load: Option<Box<dyn FnOnce(&mut EventCtx, &mut App, Option<T>) -> Transition>>,
|
||||
}
|
||||
|
||||
impl<T: 'static + DeserializeOwned> FileLoader<T> {
|
||||
pub fn new(
|
||||
_: &mut EventCtx,
|
||||
path: String,
|
||||
on_load: Box<dyn Fn(&mut EventCtx, &mut App, Option<T>) -> Transition>,
|
||||
on_load: Box<dyn FnOnce(&mut EventCtx, &mut App, Option<T>) -> Transition>,
|
||||
) -> Box<dyn State> {
|
||||
Box::new(FileLoader { path, on_load })
|
||||
Box::new(FileLoader {
|
||||
path,
|
||||
on_load: Some(on_load),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -98,7 +105,7 @@ mod native_loader {
|
||||
fn event(&mut self, ctx: &mut EventCtx, app: &mut App) -> Transition {
|
||||
ctx.loading_screen(format!("load {}", self.path), |ctx, timer| {
|
||||
// Assumes a binary file
|
||||
(self.on_load)(
|
||||
(self.on_load.take().unwrap())(
|
||||
ctx,
|
||||
app,
|
||||
abstutil::maybe_read_binary(self.path.clone(), timer).ok(),
|
||||
@ -130,7 +137,7 @@ mod wasm_loader {
|
||||
// compatible with winit's event loop.
|
||||
pub struct FileLoader<T> {
|
||||
response: oneshot::Receiver<Vec<u8>>,
|
||||
on_load: Box<dyn Fn(&mut EventCtx, &mut App, Option<T>) -> Transition>,
|
||||
on_load: Option<Box<dyn FnOnce(&mut EventCtx, &mut App, Option<T>) -> Transition>>,
|
||||
panel: Panel,
|
||||
started: Instant,
|
||||
url: String,
|
||||
@ -140,7 +147,7 @@ mod wasm_loader {
|
||||
pub fn new(
|
||||
ctx: &mut EventCtx,
|
||||
path: String,
|
||||
on_load: Box<dyn Fn(&mut EventCtx, &mut App, Option<T>) -> Transition>,
|
||||
on_load: Box<dyn FnOnce(&mut EventCtx, &mut App, Option<T>) -> Transition>,
|
||||
) -> Box<dyn State> {
|
||||
let url = if cfg!(feature = "wasm_s3") {
|
||||
format!(
|
||||
@ -177,7 +184,7 @@ mod wasm_loader {
|
||||
|
||||
Box::new(FileLoader {
|
||||
response: rx,
|
||||
on_load,
|
||||
on_load: Some(on_load),
|
||||
panel: ctx.make_loading_screen(Text::from(Line(format!("Loading {}...", url)))),
|
||||
started: Instant::now(),
|
||||
url,
|
||||
@ -194,7 +201,7 @@ mod wasm_loader {
|
||||
|
||||
// TODO Plumb failures
|
||||
let obj: T = abstutil::from_binary(&resp).unwrap();
|
||||
return (self.on_load)(ctx, app, Some(obj));
|
||||
return (self.on_load.take().unwrap())(ctx, app, Some(obj));
|
||||
}
|
||||
|
||||
self.panel = ctx.make_loading_screen(Text::from_multiline(vec![
|
||||
|
@ -417,10 +417,7 @@ impl State for Proposals {
|
||||
Box::new(move |ctx, app| {
|
||||
// Apply edits before setting up the sandbox, for simplicity
|
||||
let maybe_err = ctx.loading_screen("apply edits", |ctx, mut timer| {
|
||||
match PermanentMapEdits::from_permanent(
|
||||
edits.clone(),
|
||||
&app.primary.map,
|
||||
) {
|
||||
match PermanentMapEdits::from_permanent(edits, &app.primary.map) {
|
||||
Ok(edits) => {
|
||||
apply_map_edits(ctx, app, edits);
|
||||
app.primary
|
||||
|
@ -65,7 +65,7 @@ impl GameplayState for PlayScenario {
|
||||
)) {
|
||||
GameplayMode::PlayScenario(
|
||||
app.primary.map.get_name().clone(),
|
||||
scenario.clone(),
|
||||
scenario,
|
||||
Vec::new(),
|
||||
)
|
||||
} else {
|
||||
|
@ -618,15 +618,12 @@ impl State for SandboxLoader {
|
||||
ctx,
|
||||
abstutil::path_prebaked_results(app.primary.map.get_name(), &scenario_name),
|
||||
Box::new(move |_, _, prebaked| {
|
||||
let scenario_name = scenario_name.clone();
|
||||
Transition::Multi(vec![
|
||||
Transition::Pop,
|
||||
Transition::ModifyState(Box::new(move |state, _, _| {
|
||||
let loader = state.downcast_mut::<SandboxLoader>().unwrap();
|
||||
loader.stage = Some(LoadStage::GotPrebaked(
|
||||
scenario_name.clone(),
|
||||
prebaked,
|
||||
));
|
||||
loader.stage =
|
||||
Some(LoadStage::GotPrebaked(scenario_name, prebaked));
|
||||
})),
|
||||
])
|
||||
}),
|
||||
|
Loading…
Reference in New Issue
Block a user