use bevy::prelude::*;
use bevy_controls::{
analog::{
analog_action_reader::AnalogActionReader, analog_control::AnalogControl,
analog_inputs::AnalogInputs,
},
button::{
button_action_reader::ButtonActionReader, button_control::ButtonControl, buttons::Buttons,
},
controls_plugin::ControlsPlugin,
};
use bevy_inspector_egui::{bevy_egui::EguiPlugin, quick::WorldInspectorPlugin};
#[derive(Debug, Clone, Eq, PartialEq, Hash, Default, States, Reflect)]
enum ControlContext {
#[default]
MainMenu,
Game,
OpenInventory,
Paused,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Reflect)]
enum ControlAction {
Test1,
TestAnalog1,
TestMovementX,
TestMovementY,
}
fn main() {
App::new()
.register_type::<ButtonControl<ControlContext, ControlAction>>()
.register_type::<AnalogControl<ControlContext, ControlAction>>()
.add_plugins((
DefaultPlugins,
EguiPlugin::default(),
WorldInspectorPlugin::new(),
ControlsPlugin::<ControlContext, ControlAction>::default(),
))
.add_systems(Startup, setup)
.add_systems(Update, (update_state, update))
.run();
}
fn update(
mut controls: Query<&mut ButtonControl<ControlContext, ControlAction>>,
analog_controls: Query<&AnalogControl<ControlContext, ControlAction>>,
) {
if controls.action_just_pressed(ControlAction::Test1) {
info!("Executed TEST Action!");
}
if let Some(test_analog) = analog_controls.read_action(ControlAction::TestAnalog1) {
info!("Test analog value: {}", test_analog);
}
if let Some(move_x) = analog_controls.read_action(ControlAction::TestMovementX)
&& let Some(move_y) = analog_controls.read_action(ControlAction::TestMovementY)
{
let mut movement = Vec2::new(move_x, move_y);
if movement.length() > 1. {
movement = movement.normalize_or_zero();
}
info!("Test Movement: {}", movement);
}
}
fn setup(mut commands: Commands) {
commands.spawn(Camera2d);
commands.spawn((
Name::new("Test1 Control"),
ButtonControl::new(
ControlAction::Test1,
vec![ControlContext::MainMenu],
vec![
Buttons::Keyboard(KeyCode::Enter),
Buttons::Mouse(MouseButton::Left),
Buttons::Gamepad(GamepadButton::North),
],
),
));
commands.spawn((
Name::new("TestAnalog1 Control"),
AnalogControl::new(
ControlAction::TestAnalog1,
vec![ControlContext::Paused],
vec![
AnalogInputs::Gamepad(GamepadButton::RightTrigger2),
AnalogInputs::Button(Buttons::Gamepad(GamepadButton::North), 1.),
AnalogInputs::Button(Buttons::Gamepad(GamepadButton::South), -1.),
],
),
));
commands.spawn((
Name::new("Test Movement X"),
AnalogControl::new(
ControlAction::TestMovementX,
vec![ControlContext::Game, ControlContext::OpenInventory],
vec![
AnalogInputs::GamepadAxis(GamepadAxis::LeftStickX),
AnalogInputs::Button(Buttons::Keyboard(KeyCode::KeyA), -1.),
AnalogInputs::Button(Buttons::Keyboard(KeyCode::KeyD), 1.),
],
),
));
commands.spawn((
Name::new("Test Movement Y"),
AnalogControl::new(
ControlAction::TestMovementY,
vec![ControlContext::Game, ControlContext::OpenInventory],
vec![
AnalogInputs::GamepadAxis(GamepadAxis::LeftStickY),
AnalogInputs::Button(Buttons::Keyboard(KeyCode::KeyS), -1.),
AnalogInputs::Button(Buttons::Keyboard(KeyCode::KeyW), 1.),
],
),
));
}
fn update_state(
context: Res<State<ControlContext>>,
mut next_context: ResMut<NextState<ControlContext>>,
input: Res<ButtonInput<KeyCode>>,
) {
if !input.just_pressed(KeyCode::Space) {
return;
}
let next_state = match context.get() {
ControlContext::MainMenu => ControlContext::Game,
ControlContext::Game => ControlContext::OpenInventory,
ControlContext::OpenInventory => ControlContext::Paused,
ControlContext::Paused => ControlContext::MainMenu,
};
next_context.set(next_state);
}