state transitions for nicely handling a few things... in particular,

clearing splash screen wizard state so we dont get stuck on a choice ;)
This commit is contained in:
Dustin Carlino 2019-06-22 19:53:10 -07:00
parent 551866169a
commit 3958ec556e
7 changed files with 49 additions and 24 deletions

View File

@ -93,8 +93,6 @@ impl State for ABTestMode {
}
if self.menu.action("quit") {
// TODO Should we clear edits too?
ui.primary.reset_sim();
// Note destroying mode.secondary has some noticeable delay.
return (Transition::Pop, EventLoopMode::InputOnly);
}
@ -107,7 +105,6 @@ impl State for ABTestMode {
}
if self.menu.action("scoreboard") {
self.speed.pause();
return (
Transition::Push(Box::new(score::Scoreboard::new(
ctx,
@ -178,6 +175,15 @@ impl State for ABTestMode {
self.menu.draw(g);
self.speed.draw(g);
}
fn on_suspend(&mut self, _: &mut UI) {
self.speed.pause();
}
fn on_destroy(&mut self, ui: &mut UI) {
// TODO Should we clear edits too?
ui.primary.reset_sim();
}
}
impl ABTestMode {

View File

@ -92,26 +92,15 @@ impl State for EditMode {
}
if self.menu.action("quit") {
// TODO Warn about unsaved edits
// TODO Maybe put a loading screen around these.
ui.primary
.map
.recalculate_pathfinding_after_edits(&mut Timer::new("apply pending map edits"));
return (Transition::Pop, EventLoopMode::InputOnly);
}
if self.menu.action("sandbox mode") {
ui.primary
.map
.recalculate_pathfinding_after_edits(&mut Timer::new("apply pending map edits"));
return (
Transition::Replace(Box::new(SandboxMode::new(ctx))),
EventLoopMode::InputOnly,
);
}
if self.menu.action("debug mode") {
ui.primary
.map
.recalculate_pathfinding_after_edits(&mut Timer::new("apply pending map edits"));
return (
Transition::Replace(Box::new(DebugMode::new(ctx, ui))),
EventLoopMode::InputOnly,
@ -316,6 +305,14 @@ impl State for EditMode {
self.common.draw(g, ui);
self.menu.draw(g);
}
fn on_destroy(&mut self, ui: &mut UI) {
// TODO Warn about unsaved edits
// TODO Maybe put a loading screen around these.
ui.primary
.map
.recalculate_pathfinding_after_edits(&mut Timer::new("apply pending map edits"));
}
}
struct Saving {

View File

@ -12,10 +12,6 @@ pub struct Game {
pub ui: UI,
}
// TODO Need to reset_sim() when entering Edit, Tutorial, Mission, or ABTest and when leaving
// Tutorial and ABTest. Expressing this manually right now is quite tedious; maybe having on_enter
// and on_exit would be cleaner.
impl Game {
pub fn new(flags: Flags, ctx: &mut EventCtx) -> Game {
let splash = !flags.no_splash
@ -52,17 +48,18 @@ impl GUI for Game {
match transition {
Transition::Keep => {}
Transition::Pop => {
self.states.pop();
self.states.pop().unwrap().on_destroy(&mut self.ui);
if self.states.is_empty() {
self.before_quit(ctx.canvas);
std::process::exit(0);
}
}
Transition::Push(state) => {
self.states.last_mut().unwrap().on_suspend(&mut self.ui);
self.states.push(state);
}
Transition::Replace(state) => {
self.states.pop();
self.states.pop().unwrap().on_destroy(&mut self.ui);
self.states.push(state);
}
}
@ -120,6 +117,12 @@ pub trait State {
fn draw_default_ui(&self) -> bool {
true
}
// Before we push a new state on top of this one, call this.
fn on_suspend(&mut self, _: &mut UI) {}
// Before this state is popped or replaced, call this.
fn on_destroy(&mut self, _: &mut UI) {}
// We don't need an on_enter -- the constructor for the state can just do it.
}
pub enum Transition {

View File

@ -268,7 +268,6 @@ impl State for SandboxMode {
false,
);
} else if self.menu.action("jump to specific time") {
self.speed.pause();
return (
Transition::Push(Box::new(JumpingToTime {
wizard: Wizard::new(),
@ -314,6 +313,10 @@ impl State for SandboxMode {
_ => unreachable!(),
}*/
}
fn on_suspend(&mut self, _: &mut UI) {
self.speed.pause();
}
}
struct JumpingToTime {

View File

@ -67,6 +67,10 @@ impl State for SplashScreen {
fn draw(&self, g: &mut GfxCtx, _: &UI) {
self.wizard.draw(g);
}
fn on_suspend(&mut self, _: &mut UI) {
self.wizard.reset();
}
}
const SPEED: Speed = Speed::const_meters_per_second(20.0);

View File

@ -43,7 +43,6 @@ impl State for TutorialMode {
ctx.canvas.handle_event(ctx.input);
if self.menu.action("quit") {
ui.primary.reset_sim();
return (Transition::Pop, EventLoopMode::InputOnly);
}
@ -53,6 +52,10 @@ impl State for TutorialMode {
fn draw(&self, g: &mut GfxCtx, _: &UI) {
self.menu.draw(g);
}
fn on_destroy(&mut self, ui: &mut UI) {
ui.primary.reset_sim();
}
}
struct Part2 {
@ -69,7 +72,6 @@ impl State for Part2 {
txt.add_line("".to_string());
txt.add_line("Great! Press ENTER to continue.".to_string());
if ctx.input.key_pressed(Key::Enter, "next step of tutorial") {
ui.primary.reset_sim();
return (Transition::Pop, EventLoopMode::InputOnly);
}
}
@ -77,7 +79,6 @@ impl State for Part2 {
ctx.canvas.handle_event(ctx.input);
if self.menu.action("quit") {
ui.primary.reset_sim();
return (Transition::Pop, EventLoopMode::InputOnly);
}
@ -87,4 +88,8 @@ impl State for Part2 {
fn draw(&self, g: &mut GfxCtx, _: &UI) {
self.menu.draw(g);
}
fn on_destroy(&mut self, ui: &mut UI) {
ui.primary.reset_sim();
}
}

View File

@ -63,6 +63,13 @@ impl Wizard {
None
}
pub fn reset(&mut self) {
assert!(self.tb.is_none());
assert!(self.menu.is_none());
assert!(self.log_scroller.is_none());
self.confirmed_state.clear();
}
fn input_with_text_box<R: Cloneable>(
&mut self,
query: &str,