Adopt actions framework
parent
494cdce42e
commit
09e6c66788
@ -0,0 +1,137 @@
|
|||||||
|
use super::*;
|
||||||
|
|
||||||
|
pub(crate) struct GameActionsPlugin;
|
||||||
|
|
||||||
|
impl Plugin for GameActionsPlugin {
|
||||||
|
fn build(&self, app: &mut App) {
|
||||||
|
app.add_plugins((
|
||||||
|
ActionsPlugin::<SimAction>::new()
|
||||||
|
.bind(SimAction::Toggle, [Binding::Key(KeyCode::Space)])
|
||||||
|
.bind(SimAction::Step, [Binding::Key(KeyCode::KeyN)])
|
||||||
|
.bind(SimAction::Reset, [Binding::Key(KeyCode::KeyR)]),
|
||||||
|
ActionsPlugin::<AudioAction>::new()
|
||||||
|
.bind(AudioAction::Toggle, [Binding::Key(KeyCode::KeyM)]),
|
||||||
|
ActionsPlugin::<Action>::new()
|
||||||
|
.bind(Action::ZoomIn, [Binding::Key(KeyCode::Equal)])
|
||||||
|
.bind(Action::ZoomOut, [Binding::Key(KeyCode::Minus)])
|
||||||
|
.bind(Action::Quit, [Binding::Key(KeyCode::Escape)]),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Eq, PartialEq, Hash, GameAction, Default)]
|
||||||
|
pub(crate) enum SimAction {
|
||||||
|
#[action_handler(SimAction::toggle)]
|
||||||
|
Toggle,
|
||||||
|
#[action_handler(SimAction::step)]
|
||||||
|
Step,
|
||||||
|
#[action_handler(SimAction::reset)]
|
||||||
|
Reset,
|
||||||
|
#[action_handler(SimAction::wipe)]
|
||||||
|
Wipe,
|
||||||
|
#[default]
|
||||||
|
None,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SimAction {
|
||||||
|
/// When the user toggles between Play/Pause simulation, just update the state
|
||||||
|
fn toggle(
|
||||||
|
curr: Res<State<SimulationPlayback>>,
|
||||||
|
mut next: ResMut<NextState<SimulationPlayback>>,
|
||||||
|
mut last_board_state: ResMut<LastBoardState>,
|
||||||
|
coordinates: Query<&Coordinates, With<Cell>>,
|
||||||
|
) {
|
||||||
|
next.set(match curr.get() {
|
||||||
|
SimulationPlayback::Run | SimulationPlayback::Step => {
|
||||||
|
// Run | Step -> Pause
|
||||||
|
SimulationPlayback::Pause
|
||||||
|
}
|
||||||
|
SimulationPlayback::Pause => {
|
||||||
|
// Capture current state before running
|
||||||
|
last_board_state.coordinates = coordinates.iter().cloned().collect();
|
||||||
|
// Pause -> Run
|
||||||
|
SimulationPlayback::Run
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// When the user wants to step the simulation, just enter the SimulationStep state
|
||||||
|
// TODO: Should switch back to Pause automatically after step if Step is the current state
|
||||||
|
fn step(mut next: ResMut<NextState<SimulationPlayback>>) {
|
||||||
|
next.set(SimulationPlayback::Step);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset board to last saved state (before running, or before wiping)
|
||||||
|
fn reset(
|
||||||
|
last_board_state: Res<LastBoardState>,
|
||||||
|
mut lifecycle: MessageWriter<Lifecycle>,
|
||||||
|
cells: Query<Entity, With<Cell>>,
|
||||||
|
mut commands: Commands,
|
||||||
|
) {
|
||||||
|
// TODO: reconcile board instead of despawn/spawning the world
|
||||||
|
cells.iter().for_each(|e| {
|
||||||
|
commands.entity(e).despawn();
|
||||||
|
});
|
||||||
|
last_board_state.coordinates.iter().for_each(|c| {
|
||||||
|
lifecycle.write(Lifecycle::Alive(c.clone()));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wipe all cells from the board
|
||||||
|
fn wipe(cells: Query<Entity, With<Cell>>, mut commands: Commands) {
|
||||||
|
cells.iter().for_each(|e| {
|
||||||
|
commands.entity(e).despawn();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Eq, PartialEq, Hash, GameAction, Default)]
|
||||||
|
pub(crate) enum Action {
|
||||||
|
#[action_handler(Action::zoom_in)]
|
||||||
|
ZoomIn,
|
||||||
|
#[action_handler(Action::zoom_out)]
|
||||||
|
ZoomOut,
|
||||||
|
#[action_handler(Action::quit)]
|
||||||
|
Quit,
|
||||||
|
#[default]
|
||||||
|
None,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Action {
|
||||||
|
fn zoom_in(mut projection: Query<&mut Projection>) {
|
||||||
|
projection.iter_mut().for_each(|mut p| match *p {
|
||||||
|
Projection::Orthographic(ref mut o) => {
|
||||||
|
o.scale *= 0.5;
|
||||||
|
}
|
||||||
|
_ => todo!(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
fn zoom_out(mut projection: Query<&mut Projection>) {
|
||||||
|
projection.iter_mut().for_each(|mut p| match *p {
|
||||||
|
Projection::Orthographic(ref mut o) => {
|
||||||
|
o.scale /= 0.5;
|
||||||
|
}
|
||||||
|
_ => todo!(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
fn quit(mut writer: MessageWriter<AppExit>) {
|
||||||
|
writer.write(AppExit::Success);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Eq, PartialEq, Hash, GameAction, Default)]
|
||||||
|
pub(crate) enum AudioAction {
|
||||||
|
#[action_handler(AudioAction::toggle)]
|
||||||
|
Toggle,
|
||||||
|
#[default]
|
||||||
|
None,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AudioAction {
|
||||||
|
fn toggle(curr: Res<State<AudioPlayback>>, mut next: ResMut<NextState<AudioPlayback>>) {
|
||||||
|
next.set(match curr.get() {
|
||||||
|
AudioPlayback::Play => AudioPlayback::Mute,
|
||||||
|
AudioPlayback::Mute => AudioPlayback::Play,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue