Commit 3fe0bbf9 authored by neosam's avatar neosam
Browse files

Merge branch 'rahix/fix-state-machine' into 'master'

fix state machine (hack)

See merge request !9
parents ad9e0e3a e4bc394d
......@@ -49,12 +49,17 @@ pub trait State {
pub struct StateInitializer {
state_machine: rc::Rc<cell::RefCell<StateMachine>>,
generation: usize,
}
impl StateInitializer {
fn new(state_machine: &rc::Rc<cell::RefCell<StateMachine>>) -> StateInitializer {
fn new(
state_machine: &rc::Rc<cell::RefCell<StateMachine>>,
generation: usize,
) -> StateInitializer {
StateInitializer {
state_machine: state_machine.clone(),
generation,
}
}
......@@ -78,10 +83,16 @@ impl StateInitializer {
// them once a state becomes inactive (or at least drop the associated closure to
// invalidate it).
let state_machine = self.state_machine.clone();
let current_generation = self.generation;
let id = id.to_owned();
let canvas =
utils::get_element_by_id::<web_sys::HtmlCanvasElement>("game-canvas").unwrap();
move |event| {
if current_generation != StateMachine::current_generation(&state_machine) {
crate::console_warn!("Wrong generation in event handler, ignoring ...");
return;
}
let event = event
.dyn_ref::<web_sys::MouseEvent>()
.expect("no mouse event?");
......@@ -120,20 +131,30 @@ impl StateStorage {
}
pub struct StateMachine {
/// Stack of states that are currently "alive".
///
/// Only the state at the top of the stack is active and can receive events/process updates.
states: Vec<StateStorage>,
/// Generation counter.
///
/// Increments everytime a state-transition happens to invalidate any handlers which might
/// trigger afterwards.
generation: usize,
}
impl StateMachine {
pub fn launch<S: State + 'static>(initial: S) {
let state_machine = rc::Rc::new(cell::RefCell::new(StateMachine {
states: vec![StateStorage::new(initial)],
generation: 0,
}));
let t = {
let sm = state_machine.clone();
let mut sm = sm.borrow_mut();
let generation = sm.generation;
sm.current_state()
.init(StateInitializer::new(&state_machine))
.init(StateInitializer::new(&state_machine, generation))
};
StateMachine::handle_transition(state_machine, t);
......@@ -147,6 +168,10 @@ impl StateMachine {
&mut *self.current_storage().state
}
pub fn current_generation(state_machine: &rc::Rc<cell::RefCell<Self>>) -> usize {
state_machine.borrow().generation
}
pub fn handle_event(state_machine: rc::Rc<cell::RefCell<Self>>, target: &str, event: Event) {
let t = {
let sm = state_machine.clone();
......@@ -158,6 +183,7 @@ impl StateMachine {
}
fn handle_transition(state_machine: rc::Rc<cell::RefCell<Self>>, transition: Transition) {
let current_generation = StateMachine::current_generation(&state_machine);
match transition {
Transition::Keep => {
// Recursively call this function with the real transition type
......@@ -178,6 +204,14 @@ impl StateMachine {
let t = {
let sm = state_machine.clone();
let mut sm = sm.borrow_mut();
if sm.generation != current_generation {
// The requestAnimationFrame() was scheduled before a transition happend so
// break the cycle now as the next state is active and we're not needed
// anymore.
return;
}
sm.current_storage().last_transition = Some(transition);
sm.current_state().update()
};
......@@ -203,8 +237,10 @@ impl StateMachine {
let mut sm = sm.borrow_mut();
sm.current_state().deinit();
*sm.current_storage() = StateStorage::with_boxed(new);
sm.generation += 1;
let generation = sm.generation;
sm.current_state()
.init(StateInitializer::new(&state_machine))
.init(StateInitializer::new(&state_machine, generation))
};
StateMachine::handle_transition(state_machine, t);
......@@ -215,8 +251,10 @@ impl StateMachine {
let mut sm = sm.borrow_mut();
sm.current_state().deinit();
sm.states.push(StateStorage::with_boxed(new));
sm.generation += 1;
let generation = sm.generation;
sm.current_state()
.init(StateInitializer::new(&state_machine))
.init(StateInitializer::new(&state_machine, generation))
};
StateMachine::handle_transition(state_machine, t);
......@@ -227,8 +265,10 @@ impl StateMachine {
let mut sm = sm.borrow_mut();
sm.current_state().deinit();
sm.states.pop().unwrap();
sm.generation += 1;
let generation = sm.generation;
sm.current_state()
.init(StateInitializer::new(&state_machine))
.init(StateInitializer::new(&state_machine, generation))
};
StateMachine::handle_transition(state_machine, t);
......
use crate::resources;
use crate::state;
use crate::svg_loader;
use crate::utils;
use crate::resources;
pub struct InGameState {
gui_svg: web_sys::SvgElement,
......@@ -18,8 +18,7 @@ impl InGameState {
let world = legion::World::default();
let schedule = legion::Schedule::builder()
.build();
let schedule = legion::Schedule::builder().build();
InGameState {
gui_svg: utils::get_element_by_id("ingame-ui").unwrap(),
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment