be able to trigger a loading screen anywhere

This commit is contained in:
Dustin Carlino 2019-05-04 16:45:23 -07:00
parent eed33931de
commit 798a7b5354
6 changed files with 85 additions and 55 deletions

View File

@ -1,7 +1,6 @@
use crate::abtest::{ABTestMode, State};
use crate::game::{GameState, Mode};
use crate::ui::{Flags, PerMapUI, UI};
use abstutil::Timer;
use ezgui::{EventCtx, GfxCtx, Key, LogScroller, ModalMenu, Wizard, WrappedWizard};
use map_model::Map;
use sim::{ABTest, SimFlags};
@ -103,35 +102,37 @@ fn launch_test(test: &ABTest, ui: &mut UI, ctx: &mut EventCtx) -> Mode {
// TODO Cheaper to load the edits for the map and then instantiate the scenario for the
// primary.
let mut timer = Timer::new("setup A/B test");
let primary = PerMapUI::new(
Flags {
sim_flags: SimFlags {
load: load.clone(),
rng_seed,
run_name: format!("{} with {}", test.test_name, test.edits1_name),
edits_name: test.edits1_name.clone(),
let (primary, secondary) = ctx.loading_screen(|ctx, timer| {
let primary = PerMapUI::new(
Flags {
sim_flags: SimFlags {
load: load.clone(),
rng_seed,
run_name: format!("{} with {}", test.test_name, test.edits1_name),
edits_name: test.edits1_name.clone(),
},
..current_flags.clone()
},
..current_flags.clone()
},
&ui.cs,
ctx.prerender,
&mut timer,
);
let secondary = PerMapUI::new(
Flags {
sim_flags: SimFlags {
load,
rng_seed,
run_name: format!("{} with {}", test.test_name, test.edits2_name),
edits_name: test.edits2_name.clone(),
&ui.cs,
ctx.prerender,
timer,
);
let secondary = PerMapUI::new(
Flags {
sim_flags: SimFlags {
load,
rng_seed,
run_name: format!("{} with {}", test.test_name, test.edits2_name),
edits_name: test.edits2_name.clone(),
},
..current_flags.clone()
},
..current_flags.clone()
},
&ui.cs,
ctx.prerender,
&mut timer,
);
&ui.cs,
ctx.prerender,
timer,
);
(primary, secondary)
});
ui.primary = primary;
let mut mode = ABTestMode::new(ctx);

View File

@ -246,8 +246,9 @@ fn splash_screen(
// This retains no state, but that's probably fine.
let mut flags = ui.primary.current_flags.clone();
flags.sim_flags.load = PathBuf::from(format!("../data/maps/{}.abst", name));
let mut timer = Timer::new(&format!("load {}", name));
*ui = UI::new(flags, ctx.prerender, ctx.canvas, &mut timer);
*ui = ctx.loading_screen(|ctx, timer| {
UI::new(flags, ctx.prerender, ctx.canvas, timer)
});
break Some(Mode::Sandbox(SandboxMode::new(ctx.canvas)));
} else if wizard.aborted() {
break Some(Mode::SplashScreen(Wizard::new(), maybe_screensaver.take()));

View File

@ -2,7 +2,7 @@ use crate::game::Mode;
use crate::mission::MissionEditMode;
use crate::sandbox::SandboxMode;
use crate::ui::UI;
use abstutil::{Timer, WeightedUsizeChoice};
use abstutil::WeightedUsizeChoice;
use ezgui::{
Color, Drawable, EventCtx, GfxCtx, Key, LogScroller, ModalMenu, Wizard, WrappedWizard,
};
@ -58,12 +58,14 @@ impl ScenarioEditor {
} else if menu.action("edit") {
*self = ScenarioEditor::EditScenario(scenario.clone(), Wizard::new());
} else if menu.action("instantiate") {
scenario.instantiate(
&mut ui.primary.sim,
&ui.primary.map,
&mut ui.primary.current_flags.sim_flags.make_rng(),
&mut Timer::new("instantiate scenario"),
);
ctx.loading_screen(|_, timer| {
scenario.instantiate(
&mut ui.primary.sim,
&ui.primary.map,
&mut ui.primary.current_flags.sim_flags.make_rng(),
timer,
);
});
return Some(Mode::Sandbox(SandboxMode::new(ctx.canvas)));
} else if menu.action("visualize") {
let neighborhoods = Neighborhood::load_all(

View File

@ -91,13 +91,18 @@ impl AgentSpawner {
None => {
if ui.primary.sim.is_empty() {
if sandbox_menu.action("seed the sim with agents") {
Scenario::scaled_run(map, ui.primary.current_flags.num_agents).instantiate(
&mut ui.primary.sim,
map,
&mut ui.primary.current_flags.sim_flags.make_rng(),
&mut Timer::new("seed sim"),
);
ui.primary.sim.step(map);
// TODO This covers up the map. :\
ctx.loading_screen(|_, timer| {
let map = &ui.primary.map;
Scenario::scaled_run(map, ui.primary.current_flags.num_agents)
.instantiate(
&mut ui.primary.sim,
map,
&mut ui.primary.current_flags.sim_flags.make_rng(),
timer,
);
ui.primary.sim.step(map);
});
}
}
}

View File

@ -1,4 +1,6 @@
use crate::runner::LoadingScreen;
use crate::{Canvas, Color, UserInput};
use abstutil::Timer;
use geom::Polygon;
use glium::implement_vertex;
use std::cell::Cell;
@ -112,6 +114,23 @@ pub struct EventCtx<'a> {
// TODO These two probably shouldn't be public
pub canvas: &'a mut Canvas,
pub prerender: &'a Prerender<'a>,
pub(crate) program: &'a glium::Program,
}
impl<'a> EventCtx<'a> {
pub fn loading_screen<O, F: FnOnce(&mut EventCtx, &mut Timer) -> O>(&mut self, f: F) -> O {
let mut timer = Timer::new_with_sink(
"Loading...",
Box::new(LoadingScreen::new(
self.prerender,
self.program,
self.canvas.window_width,
self.canvas.window_height,
)),
);
f(self, &mut timer)
}
}
fn f32_to_u8(x: f32) -> u8 {

View File

@ -48,7 +48,12 @@ pub(crate) struct State<G: GUI> {
impl<G: GUI> State<G> {
// The bool indicates if the input was actually used.
fn event(mut self, ev: Event, prerender: &Prerender) -> (State<G>, EventLoopMode, bool) {
fn event(
mut self,
ev: Event,
prerender: &Prerender,
program: &glium::Program,
) -> (State<G>, EventLoopMode, bool) {
// Clear out the possible keys
match self.context_menu {
ContextMenu::Inactive(_) => {
@ -67,6 +72,7 @@ impl<G: GUI> State<G> {
input: &mut input,
canvas: &mut canvas,
prerender,
program,
})
})) {
Ok(pair) => pair,
@ -195,7 +201,6 @@ pub fn run<G: GUI, F: FnOnce(&mut Canvas, &Prerender, &mut Timer) -> G>(
let mut timer = Timer::new_with_sink(
"Loading application...",
Box::new(LoadingScreen::new(
&display,
&prerender,
&program,
initial_width,
@ -261,7 +266,7 @@ fn loop_forever<G: GUI>(
let mut any_input_used = false;
for event in new_events {
let (new_state, mode, input_used) = state.event(event, &prerender);
let (new_state, mode, input_used) = state.event(event, &prerender, &program);
if input_used {
any_input_used = true;
}
@ -313,8 +318,7 @@ fn loop_forever<G: GUI>(
}
}
struct LoadingScreen<'a> {
display: &'a glium::Display,
pub struct LoadingScreen<'a> {
canvas: Canvas,
prerender: &'a Prerender<'a>,
program: &'a glium::Program,
@ -322,8 +326,7 @@ struct LoadingScreen<'a> {
}
impl<'a> LoadingScreen<'a> {
fn new(
display: &'a glium::Display,
pub fn new(
prerender: &'a Prerender<'a>,
program: &'a glium::Program,
initial_width: f64,
@ -331,11 +334,10 @@ impl<'a> LoadingScreen<'a> {
) -> LoadingScreen<'a> {
// TODO Ew! Expensive and wacky. Fix by not storing GlyphBrush in Canvas at all.
let dejavu: &[u8] = include_bytes!("assets/DejaVuSans.ttf");
let glyphs = GlyphBrush::new(display, vec![Font::from_bytes(dejavu).unwrap()]);
let glyphs = GlyphBrush::new(prerender.display, vec![Font::from_bytes(dejavu).unwrap()]);
let canvas = Canvas::new(initial_width, initial_height, glyphs);
LoadingScreen {
display,
canvas,
prerender,
program,
@ -344,12 +346,12 @@ impl<'a> LoadingScreen<'a> {
}
fn redraw(&self, text: Text) {
let mut target = self.display.draw();
let mut target = self.prerender.display.draw();
let context_menu = ContextMenu::new();
let mut g = GfxCtx::new(
&self.canvas,
self.prerender,
self.display,
self.prerender.display,
&mut target,
self.program,
&context_menu,