use std::f64;
use input;
use input::{
GenericEvent,
UpdateEvent,
};
use {
Action,
After,
AlwaysSucceed,
Behavior,
Failure,
If,
Fail,
WaitForPressed,
WaitForReleased,
Running,
Select,
Sequence,
Status,
Success,
Wait,
WaitForever,
WhenAll,
WhenAny,
While,
};
use state::State::{
WaitForPressedState,
WaitForReleasedState,
ActionState,
FailState,
AlwaysSucceedState,
WaitState,
WaitForeverState,
IfState,
SelectState,
SequenceState,
WhileState,
WhenAllState,
WhenAnyState,
AfterState,
};
pub const RUNNING: (Status, f64) = (Running, 0.0);
pub struct ActionArgs<'a, E: 'a, A: 'a, S: 'a> {
pub event: &'a E,
pub dt: f64,
pub action: &'a A,
pub state: &'a mut Option<S>,
}
#[derive(Clone, Deserialize, Serialize, PartialEq)]
pub enum State<A, S> {
WaitForPressedState(input::Button),
WaitForReleasedState(input::Button),
ActionState(A, Option<S>),
FailState(Box<State<A, S>>),
AlwaysSucceedState(Box<State<A, S>>),
WaitState(f64, f64),
WaitForeverState,
IfState(Box<Behavior<A>>, Box<Behavior<A>>, Status, Box<State<A, S>>),
SelectState(Vec<Behavior<A>>, usize, Box<State<A, S>>),
SequenceState(Vec<Behavior<A>>, usize, Box<State<A, S>>),
WhileState(Box<State<A, S>>, Vec<Behavior<A>>, usize, Box<State<A, S>>),
WhenAllState(Vec<Option<State<A, S>>>),
WhenAnyState(Vec<Option<State<A, S>>>),
AfterState(usize, Vec<State<A, S>>),
}
fn sequence<A, S, E, F>(
select: bool,
upd: Option<f64>,
seq: &Vec<Behavior<A>>,
i: &mut usize,
cursor: &mut Box<State<A, S>>,
e: &E,
f: &mut F
) -> (Status, f64)
where
A: Clone,
E: GenericEvent,
F: FnMut(ActionArgs<E, A, S>) -> (Status, f64)
{
let (status, inv_status) = if select {
(Failure, Success)
} else {
(Success, Failure)
};
let mut remaining_dt = upd.unwrap_or(0.0);
let mut remaining_e;
while *i < seq.len() {
match cursor.event(
match upd {
Some(_) => {
remaining_e = UpdateEvent::from_dt(remaining_dt, e).unwrap();
&remaining_e
}
_ => e
},
f) {
(Running, _) => { break; },
(s, new_dt) if s == inv_status => {
return (inv_status, new_dt);
}
(s, new_dt) if s == status => {
remaining_dt = match upd {
Some(_) => new_dt,
_ => if *i == seq.len() - 1 {
return (status, new_dt)
} else {
*i += 1;
**cursor = State::new(seq[*i].clone());
return RUNNING
}
}
}
_ => unreachable!()
};
*i += 1;
if *i >= seq.len() { return (status, remaining_dt); }
**cursor = State::new(seq[*i].clone());
}
RUNNING
}
fn when_all<A, S, E, F>(
any: bool,
upd: Option<f64>,
cursors: &mut Vec<Option<State<A, S>>>,
e: &E,
f: &mut F
) -> (Status, f64)
where
A: Clone,
E: GenericEvent,
F: FnMut(ActionArgs<E, A, S>) -> (Status, f64)
{
let (status, inv_status) = if any {
(Failure, Success)
} else {
(Success, Failure)
};
let mut min_dt = f64::MAX;
let mut terminated = 0;
for cur in cursors.iter_mut() {
match *cur {
None => {}
Some(ref mut cur) => {
match cur.event(e, f) {
(Running, _) => { continue; },
(s, new_dt) if s == inv_status => {
return (inv_status, new_dt);
}
(s, new_dt) if s == status => {
min_dt = min_dt.min(new_dt);
}
_ => unreachable!()
}
}
}
terminated += 1;
*cur = None;
}
match terminated {
0 if cursors.len() == 0 => (status, match upd {
Some(dt) => dt,
_ => 0.0
}),
n if cursors.len() == n => (status, min_dt),
_ => RUNNING
}
}
impl<A: Clone, S> State<A, S> {
pub fn new(behavior: Behavior<A>) -> Self {
match behavior {
WaitForPressed(button) => WaitForPressedState(button),
WaitForReleased(button) => WaitForReleasedState(button),
Action(action) => ActionState(action, None),
Fail(ev) => FailState(Box::new(State::new(*ev))),
AlwaysSucceed(ev) => AlwaysSucceedState(Box::new(State::new(*ev))),
Wait(dt) => WaitState(dt, 0.0),
WaitForever => WaitForeverState,
If(condition, success, failure) => {
let state = State::new(*condition);
IfState(success, failure, Running, Box::new(state))
}
Select(sel) => {
let state = State::new(sel[0].clone());
SelectState(sel, 0, Box::new(state))
}
Sequence(seq) => {
let state = State::new(seq[0].clone());
SequenceState(seq, 0, Box::new(state))
}
While(ev, rep) => {
let state = State::new(rep[0].clone());
WhileState(Box::new(State::new(*ev)), rep, 0, Box::new(state))
}
WhenAll(all)
=> WhenAllState(all.into_iter().map(
|ev| Some(State::new(ev))).collect()),
WhenAny(all)
=> WhenAnyState(all.into_iter().map(
|ev| Some(State::new(ev))).collect()),
After(seq)
=> AfterState(0, seq.into_iter().map(
|ev| State::new(ev)).collect()),
}
}
pub fn event<E, F>(
&mut self,
e: &E,
f: &mut F
) -> (Status, f64)
where
E: GenericEvent,
F: FnMut(ActionArgs<E, A, S>) -> (Status, f64)
{
let upd = e.update(|args| Some(args.dt)).unwrap_or(None);
match (upd, self) {
(None, &mut WaitForPressedState(button)) => {
e.press(|button_pressed| {
if button_pressed != button { return RUNNING; }
(Success, 0.0)
}).unwrap_or(RUNNING)
}
(None, &mut WaitForReleasedState(button)) => {
e.release(|button_released| {
if button_released != button { return RUNNING; }
(Success, 0.0)
}).unwrap_or(RUNNING)
}
(_, &mut ActionState(ref action, ref mut state)) => {
f(ActionArgs {
event: e,
dt: upd.unwrap_or(0.0),
action: action,
state: state
})
}
(_, &mut FailState(ref mut cur)) => {
match cur.event(e, f) {
(Running, dt) => (Running, dt),
(Failure, dt) => (Success, dt),
(Success, dt) => (Failure, dt),
}
}
(_, &mut AlwaysSucceedState(ref mut cur)) => {
match cur.event(e, f) {
(Running, dt) => (Running, dt),
(_, dt) => (Success, dt),
}
}
(Some(dt), &mut WaitState(wait_t, ref mut t)) => {
if *t + dt >= wait_t {
let remaining_dt = *t + dt - wait_t;
*t = wait_t;
(Success, remaining_dt)
} else {
*t += dt;
RUNNING
}
}
(_, &mut IfState(ref success, ref failure,
ref mut status, ref mut state)) => {
let mut remaining_dt = upd.unwrap_or(0.0);
let remaining_e;
loop {
*status = match *status {
Running => {
match state.event(e, f) {
(Running, dt) => { return (Running, dt); },
(Success, dt) => {
**state = State::new((**success).clone());
remaining_dt = dt;
Success
}
(Failure, dt) => {
**state = State::new((**failure).clone());
remaining_dt = dt;
Failure
}
}
}
_ => {
return state.event(match upd {
Some(_) => {
remaining_e = UpdateEvent::from_dt(
remaining_dt, e).unwrap();
&remaining_e
}
_ => e
}, f);
}
}
}
}
(_, &mut SelectState(ref seq, ref mut i, ref mut cursor)) => {
let select = true;
sequence(select, upd, seq, i, cursor, e, f)
}
(_, &mut SequenceState(ref seq, ref mut i, ref mut cursor)) => {
let select = false;
sequence(select, upd, seq, i, cursor, e, f)
}
(_, &mut WhileState(ref mut ev_cursor, ref rep, ref mut i,
ref mut cursor)) => {
match ev_cursor.event(e, f) {
(Running, _) => {}
x => return x,
};
let cur = cursor;
let mut remaining_dt = upd.unwrap_or(0.0);
let mut remaining_e;
loop {
match cur.event(match upd {
Some(_) => {
remaining_e = UpdateEvent::from_dt(
remaining_dt, e).unwrap();
&remaining_e
}
_ => e
},
f) {
(Failure, x) => return (Failure, x),
(Running, _) => { break },
(Success, new_dt) => {
remaining_dt = match upd {
Some(_) => new_dt,
_ => return RUNNING
}
}
};
*i += 1;
if *i >= rep.len() { *i = 0; }
**cur = State::new(rep[*i].clone());
}
RUNNING
}
(_, &mut WhenAllState(ref mut cursors)) => {
let any = false;
when_all(any, upd, cursors, e, f)
}
(_, &mut WhenAnyState(ref mut cursors)) => {
let any = true;
when_all(any, upd, cursors, e, f)
}
(_, &mut AfterState(ref mut i, ref mut cursors)) => {
let mut min_dt = f64::MAX;
for j in *i..cursors.len() {
match cursors[j].event(e, f) {
(Running, _) => { min_dt = 0.0; }
(Success, new_dt) => {
if *i == j && new_dt < min_dt {
*i += 1;
min_dt = new_dt;
} else {
return (Failure, min_dt.min(new_dt));
}
}
(Failure, new_dt) => {
return (Failure, new_dt);
}
};
}
if *i == cursors.len() {
(Success, min_dt)
} else {
RUNNING
}
}
_ => RUNNING
}
}
}