You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
138 lines
4.3 KiB
Rust
138 lines
4.3 KiB
Rust
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,
|
|
});
|
|
}
|
|
}
|