stop blindly plumbing through no-op events after any input is used. do

it more explicitly in just a few places.

fixes crash when cycling through turns while sim is running.

this makes modal menus appear laggy, but that's fine; phasing those out
anyway.
This commit is contained in:
Dustin Carlino 2020-01-23 17:11:29 -08:00
parent 89a269a59e
commit 6d016cd01b
4 changed files with 17 additions and 14 deletions

View File

@ -47,9 +47,13 @@ impl<'a> EventCtx<'a> {
}
// Use to immediately plumb through an (empty) event to something
pub fn fake_mouseover<O, F: FnMut(&mut EventCtx) -> O>(&mut self, mut cb: F) -> O {
pub fn no_op_event<O, F: FnMut(&mut EventCtx) -> O>(
&mut self,
fake_mouseover: bool,
mut cb: F,
) -> O {
let mut tmp = EventCtx {
fake_mouseover: true,
fake_mouseover,
input: UserInput::new(Event::NoOp, self.canvas),
canvas: self.canvas,
prerender: self.prerender,

View File

@ -877,7 +877,7 @@ impl CompositeBuilder {
c.clip_rect = Some(ScreenRectangle::top_left(top_left, c.container_dims));
}
ctx.fake_mouseover(|ctx| assert!(c.event(ctx).is_none()));
ctx.no_op_event(true, |ctx| assert!(c.event(ctx).is_none()));
c
}

View File

@ -432,14 +432,6 @@ fn loop_forever<G: GUI>(
// Don't draw if an event was ignored and we're not in Animation mode. Every keypress also
// fires a release event, most of which are ignored.
if any_input_used || !wait_for_events {
if any_input_used {
// But if the event caused a state-change, the drawing state might be different
// too. Need to recalculate what menu entries and such are valid. So send through
// a no-op event.
let (new_state, _, _) = state.event(Event::NoOp, &prerender, &program);
state = new_state;
}
state.draw(&prerender.display, &program, &prerender, false);
prerender.num_uploads.set(0);
}

View File

@ -42,9 +42,13 @@ impl GUI for Game {
// If we fall through, there's a new state that we need to wakeup.
match transition {
Transition::Keep => {
self.ui.per_obj.assert_chosen_used();
return EventLoopMode::InputOnly;
}
Transition::KeepWithMode(evmode) => return evmode,
Transition::KeepWithMode(evmode) => {
self.ui.per_obj.assert_chosen_used();
return evmode;
}
Transition::Pop => {
self.states.pop().unwrap().on_destroy(ctx, &mut self.ui);
if self.states.is_empty() {
@ -85,7 +89,9 @@ impl GUI for Game {
}
Transition::ApplyObjectAction(action) => {
self.ui.per_obj.action_chosen(action);
return EventLoopMode::InputOnly;
// Immediately go trigger the action. Things'll break unless current_selection
// remains the same, so DON'T redo mouseover.
return ctx.no_op_event(false, |ctx| self.event(ctx));
}
Transition::PushTwice(s1, s2) => {
self.states
@ -94,6 +100,7 @@ impl GUI for Game {
.on_suspend(ctx, &mut self.ui);
self.states.push(s1);
self.states.push(s2);
self.ui.per_obj.assert_chosen_used();
return EventLoopMode::InputOnly;
}
};
@ -101,7 +108,7 @@ impl GUI for Game {
// Let the new state initialize with a fake event. Usually these just return
// Transition::Keep, but nothing stops them from doing whatever. (For example, entering
// tutorial mode immediately pushes on a Warper.) So just recurse.
ctx.fake_mouseover(|ctx| self.event(ctx))
ctx.no_op_event(true, |ctx| self.event(ctx))
}
fn draw(&self, g: &mut GfxCtx) {