#![cfg(feature = "keyboard")]
use bevy::prelude::*;
use leafwing_input_manager::prelude::*;
#[derive(Actionlike, Clone, Copy, Debug, Reflect, PartialEq, Eq, Hash)]
enum Action {
PayRespects,
}
#[derive(Resource, Default, PartialEq, Debug)]
struct Respect(bool);
fn pay_respects(
action_state_query: Query<&ActionState<Action>, With<Player>>,
action_state_resource: Option<Res<ActionState<Action>>>,
mut respect: ResMut<Respect>,
) {
if let Ok(action_state) = action_state_query.single() {
if action_state.pressed(&Action::PayRespects) {
respect.0 = true;
}
}
if let Some(action_state) = action_state_resource {
if action_state.pressed(&Action::PayRespects) {
respect.0 = true;
}
}
}
fn respect_fades(mut respect: ResMut<Respect>) {
respect.0 = false;
}
fn remove_input_map(mut commands: Commands, query: Query<Entity, With<InputMap<Action>>>) {
for entity in query.iter() {
commands.entity(entity).remove::<InputMap<Action>>();
}
}
#[derive(Component)]
struct Player;
fn spawn_player(mut commands: Commands) {
commands
.spawn(InputMap::new([(Action::PayRespects, KeyCode::KeyF)]))
.insert(Player);
}
#[test]
fn disable_input() {
use bevy::input::InputPlugin;
let mut app = App::new();
app.add_plugins(MinimalPlugins)
.add_plugins(InputPlugin)
.add_plugins(InputManagerPlugin::<Action>::default())
.add_systems(Startup, spawn_player)
.init_resource::<ActionState<Action>>()
.insert_resource(InputMap::<Action>::new([(
Action::PayRespects,
KeyCode::KeyF,
)]))
.init_resource::<Respect>()
.add_systems(Update, pay_respects)
.add_systems(PreUpdate, respect_fades);
KeyCode::KeyF.press(app.world_mut());
app.update();
let respect = app.world().resource::<Respect>();
assert_eq!(*respect, Respect(true));
let mut action_state = app.world_mut().resource_mut::<ActionState<Action>>();
action_state.disable_all_actions();
app.update();
let respect = app.world().resource::<Respect>();
assert_eq!(*respect, Respect(true));
let mut action_state = app
.world_mut()
.query_filtered::<&mut ActionState<Action>, With<Player>>()
.single_mut(app.world_mut())
.expect("ActionState not found");
action_state.disable_all_actions();
app.update();
let respect = app.world().resource::<Respect>();
assert_eq!(*respect, Respect(false));
KeyCode::KeyF.press(app.world_mut());
app.update();
let respect = app.world().resource::<Respect>();
assert_eq!(*respect, Respect(false));
let mut action_state = app.world_mut().resource_mut::<ActionState<Action>>();
action_state.enable_all_actions();
app.update();
let respect = app.world().resource::<Respect>();
assert_eq!(*respect, Respect(true));
}
#[test]
fn release_when_input_map_removed() {
use bevy::input::InputPlugin;
let mut app = App::new();
app.add_plugins(MinimalPlugins)
.add_plugins(InputPlugin)
.add_plugins(InputManagerPlugin::<Action>::default())
.add_systems(Startup, spawn_player)
.init_resource::<ActionState<Action>>()
.insert_resource(InputMap::<Action>::new([(
Action::PayRespects,
KeyCode::KeyF,
)]))
.init_resource::<Respect>()
.add_systems(Update, (pay_respects, remove_input_map))
.add_systems(PreUpdate, respect_fades);
KeyCode::KeyF.press(app.world_mut());
app.update();
let respect = app.world().resource::<Respect>();
assert_eq!(*respect, Respect(true));
app.world_mut().remove_resource::<InputMap<Action>>();
app.update();
app.update();
let respect = app.world().resource::<Respect>();
assert_eq!(*respect, Respect(false));
KeyCode::KeyF.press(app.world_mut());
app.update();
let respect = app.world().resource::<Respect>();
assert_eq!(*respect, Respect(false));
}
#[cfg(feature = "timing")]
#[test]
fn duration() {
use bevy::input::InputPlugin;
use core::time::Duration;
const RESPECTFUL_DURATION: Duration = Duration::from_millis(5);
fn hold_f_to_pay_respects(
action_state: Res<ActionState<Action>>,
mut respect: ResMut<Respect>,
) {
if action_state.pressed(&Action::PayRespects)
&& action_state.current_duration(&Action::PayRespects) > RESPECTFUL_DURATION
{
respect.0 = true;
}
}
let mut app = App::new();
app.add_plugins(MinimalPlugins)
.add_plugins(InputPlugin)
.add_plugins(InputManagerPlugin::<Action>::default())
.add_systems(Startup, spawn_player)
.init_resource::<ActionState<Action>>()
.insert_resource(InputMap::<Action>::new([(
Action::PayRespects,
KeyCode::KeyF,
)]))
.init_resource::<Respect>()
.add_systems(Update, hold_f_to_pay_respects);
app.update();
KeyCode::KeyF.press(app.world_mut());
std::thread::sleep(2 * RESPECTFUL_DURATION);
app.update();
assert!(
app.world()
.resource::<ActionState<Action>>()
.pressed(&Action::PayRespects)
);
}