Skip to content

Commit

Permalink
Changed lifetime requirements for TransQueue. Added state_dispatcher …
Browse files Browse the repository at this point in the history
…example.
  • Loading branch information
AnneKitsune committed Oct 25, 2018
1 parent c03e7ea commit 853afe8
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 10 deletions.
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -191,5 +191,9 @@ path = "examples/prefab/main.rs"
name = "debug_lines"
path = "examples/debug_lines/main.rs"

[[example]]
name = "state_dispatcher"
path = "examples/state_dispatcher/main.rs"

[workspace]
members = ["amethyst_gltf"]
46 changes: 46 additions & 0 deletions examples/state_dispatcher/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//! An example showing how to create a dispatcher inside of a State.
extern crate amethyst;

use amethyst::Error;
use amethyst::ecs::{Dispatcher, DispatcherBuilder};
use amethyst::prelude::*;

struct StateA;

impl SimpleState<'static, 'static> for StateA {
fn update(&mut self, data: &mut StateData<GameData>) -> SimpleTrans<'static, 'static> {
println!("StateA::update()");
// Shows how to push a `Trans` through the event queue.
data.world.write_resource::<TransQueue<GameData<'static, 'static>, StateEvent>>().push_back(Box::new(|| Trans::Push(Box::new(StateB::<'static, 'static>::default()))));
Trans::None
}
}

/// StateB isn't Send + Sync
struct StateB<'a, 'b> {
dispatcher: Dispatcher<'a, 'b>,
}

impl<'a, 'b> Default for StateB<'a, 'b> {
fn default() -> Self {
StateB {
dispatcher: DispatcherBuilder::new().build(),
}
}
}

impl<'a, 'b> SimpleState<'a, 'b> for StateB<'a, 'b> {
fn update(&mut self, data: &mut StateData<GameData>) -> SimpleTrans<'a, 'b> {
println!("StateB::update()");
self.dispatcher.dispatch(&mut data.world.res);
Trans::Quit
}
}

fn main() -> Result<(), Error> {
amethyst::start_logger(Default::default());
let mut game = Application::build("./", StateA)?.build(GameDataBuilder::default())?;
game.run();
Ok(())
}
12 changes: 6 additions & 6 deletions src/app.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
//! The core engine framework.
use state::Trans;
use amethyst_ui::UiEvent;
use assets::{Loader, Source};
use core::frame_limiter::{FrameLimiter, FrameRateLimitConfig, FrameRateLimitStrategy};
Expand All @@ -14,7 +13,7 @@ use game_data::DataInit;
use log::Level;
use rayon::ThreadPoolBuilder;
use shred::Resource;
use state::{State, StateData, StateMachine};
use state::{State, StateData, StateMachine, TransQueue};
use state_event::StateEvent;
use state_event::StateEventReader;
use std::collections::VecDeque;
Expand Down Expand Up @@ -125,8 +124,9 @@ pub struct CoreApplication<'a, T, E = StateEvent, R = StateEventReader> {
/// [log]: https://crates.io/crates/log
pub type Application<'a, T> = CoreApplication<'a, T, StateEvent, StateEventReader>;

impl<'a, T: 'static, E, R> CoreApplication<'a, T, E, R>
impl<'a, T, E, R> CoreApplication<'a, T, E, R>
where
T: 'static,
E: Clone + Send + Sync + 'static,
{
/// Creates a new Application with the given initial game state.
Expand Down Expand Up @@ -294,13 +294,13 @@ where
// Read the Trans queue and apply changes.
{
let trans = {
let mut v = self.world.write_resource::<VecDeque<Trans<T, E>>>();
let mut v = self.world.write_resource::<TransQueue<T, E>>();
let x = v.drain(..).collect::<VecDeque<_>>();
x
};
let states = &mut self.states;
for tr in trans.into_iter() {
states.transition(tr, StateData::new(&mut self.world, &mut self.data));
states.transition(tr(), StateData::new(&mut self.world, &mut self.data));
}
}

Expand Down Expand Up @@ -482,7 +482,7 @@ where T: 'static{
world.add_resource(pool);
world.add_resource(EventChannel::<Event>::with_capacity(2000));
world.add_resource(EventChannel::<UiEvent>::with_capacity(40));
world.add_resource(VecDeque::<Trans<T, StateEvent>>::with_capacity(2));
world.add_resource(TransQueue::<T, StateEvent>::with_capacity(2));
world.add_resource(Errors::default());
world.add_resource(FrameLimiter::default());
world.add_resource(Stopwatch::default());
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ pub use self::error::{Error, Result};
pub use self::game_data::{DataInit, GameData, GameDataBuilder};
pub use self::logger::{start_logger, LevelFilter as LogLevelFilter, LoggerConfig, StdoutLog};
pub use self::state::{
EmptyState, EmptyTrans, SimpleState, SimpleTrans, State, StateData, StateMachine, Trans,
EmptyState, EmptyTrans, SimpleState, SimpleTrans, State, StateData, StateMachine, Trans, TransQueue,
};
pub use self::state_event::{StateEvent, StateEventReader};
pub use core::shred;
Expand Down
2 changes: 1 addition & 1 deletion src/prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ pub use config::Config;
pub use core::WithNamed;
pub use ecs::prelude::{Builder, World};
pub use game_data::{DataInit, GameData, GameDataBuilder};
pub use state::{EmptyState, EmptyTrans, SimpleState, SimpleTrans, State, StateData, Trans};
pub use state::{EmptyState, EmptyTrans, SimpleState, SimpleTrans, State, StateData, Trans, TransQueue};
pub use state_event::StateEvent;
11 changes: 9 additions & 2 deletions src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
use amethyst_input::is_close_requested;
use ecs::prelude::World;
use std::collections::VecDeque;
use std::fmt::Result as FmtResult;
use std::fmt::{Display, Formatter};
use {GameData, StateEvent};
Expand Down Expand Up @@ -54,13 +55,19 @@ pub enum Trans<T, E> {
/// if there are none.
Pop,
/// Pause the active state and push a new state onto the stack.
Push(Box<State<T, E> + Send + Sync>),
Push(Box<State<T, E>>),
/// Remove the current state on the stack and insert a different one.
Switch(Box<State<T, E> + Send + Sync>),
Switch(Box<State<T, E>>),
/// Stop and remove all states and shut down the engine.
Quit,
}

/// Event queue to trigger state `Trans` from other places than a `State`'s methods.
/// # Example:
/// ```rust, ignore
/// world.write_resource::<TransQueue<MyGameData, StateEvent>>().push_back(Box::new(|| Trans::Quit));
/// ```
pub type TransQueue<T, E> = VecDeque<Box<Fn() -> Trans<T, E> + Send + Sync + 'static>>;

/// An empty `Trans`. Made to be used with `EmptyState`.
pub type EmptyTrans = Trans<(), StateEvent>;
Expand Down

0 comments on commit 853afe8

Please sign in to comment.