a way to pop states and pass data back

This commit is contained in:
Dustin Carlino 2019-06-22 20:12:04 -07:00
parent 3958ec556e
commit e67305d084
5 changed files with 29 additions and 8 deletions

View File

@ -11,6 +11,7 @@ clipping = "0.1.1"
colorbrewer = "0.1.0"
counter = "0.4.3"
derive-new = "0.5.6"
downcast-rs = "1.0.4"
ezgui = { path = "../ezgui" }
geom = { path = "../geom" }
itertools = "0.8.0"

View File

@ -552,9 +552,13 @@ impl State for SearchOSM {
}
}
// TODO How to pass data back?
//mode.search_results = Some((filter, ids));
(Transition::Pop, EventLoopMode::InputOnly)
(
Transition::PopWithData(Box::new(|state| {
state.downcast_mut::<DebugMode>().unwrap().search_results =
Some((filter, ids));
})),
EventLoopMode::InputOnly,
)
}
InputResult::StillActive => (Transition::Keep, EventLoopMode::InputOnly),
}

View File

@ -54,6 +54,10 @@ impl GUI for Game {
std::process::exit(0);
}
}
Transition::PopWithData(cb) => {
self.states.pop().unwrap().on_destroy(&mut self.ui);
cb(self.states.last_mut().unwrap());
}
Transition::Push(state) => {
self.states.last_mut().unwrap().on_suspend(&mut self.ui);
self.states.push(state);
@ -111,7 +115,7 @@ impl GUI for Game {
}
}
pub trait State {
pub trait State: downcast_rs::Downcast {
fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI) -> (Transition, EventLoopMode);
fn draw(&self, g: &mut GfxCtx, ui: &UI);
fn draw_default_ui(&self) -> bool {
@ -125,9 +129,13 @@ pub trait State {
// We don't need an on_enter -- the constructor for the state can just do it.
}
downcast_rs::impl_downcast!(State);
pub enum Transition {
Keep,
Pop,
// If a state needs to pass data back to the parent, use this. Sadly, runtime type casting.
PopWithData(Box<FnOnce(&mut Box<State>)>),
Push(Box<State>),
Replace(Box<State>),
}

View File

@ -86,8 +86,16 @@ impl State for ScenarioEditor {
if let Some(()) = edit_scenario(&ui.primary.map, &mut self.scenario, self.wizard.wrap(ctx))
{
// TODO autosave, or at least make it clear there are unsaved edits
// TODO Need to Refresh the scenario in our parent!
return (Transition::Pop, EventLoopMode::InputOnly);
let scenario = self.scenario.clone();
return (
Transition::PopWithData(Box::new(|state| {
let mut manager = state.downcast_mut::<ScenarioManager>().unwrap();
manager.scroller =
LogScroller::new(scenario.scenario_name.clone(), scenario.describe());
manager.scenario = scenario;
})),
EventLoopMode::InputOnly,
);
} else if self.wizard.aborted() {
return (Transition::Pop, EventLoopMode::InputOnly);
}

View File

@ -21,7 +21,7 @@ impl TutorialMode {
}
impl State for TutorialMode {
fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI) -> (Transition, EventLoopMode) {
fn event(&mut self, ctx: &mut EventCtx, _: &mut UI) -> (Transition, EventLoopMode) {
let mut txt = Text::prompt("Tutorial");
txt.add_line("Click and drag to pan around".to_string());
@ -64,7 +64,7 @@ struct Part2 {
}
impl State for Part2 {
fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI) -> (Transition, EventLoopMode) {
fn event(&mut self, ctx: &mut EventCtx, _: &mut UI) -> (Transition, EventLoopMode) {
let mut txt = Text::prompt("Tutorial");
txt.add_line("Use your mouse wheel or touchpad to zoom in and out".to_string());