leafwing_input_manager/
systems.rsuse crate::prelude::updating::CentralInputStore;
#[cfg(feature = "mouse")]
use crate::user_input::{AccumulatedMouseMovement, AccumulatedMouseScroll};
#[cfg(feature = "mouse")]
use bevy::input::mouse::{MouseMotion, MouseWheel};
use crate::{
action_state::ActionState, clashing_inputs::ClashStrategy, input_map::InputMap, Actionlike,
};
use bevy::ecs::prelude::*;
use bevy::prelude::Gamepads;
use bevy::{
time::{Real, Time},
utils::Instant,
};
use crate::action_diff::{ActionDiffEvent, SummarizedActionState};
pub fn swap_to_update<A: Actionlike>(
mut query: Query<&mut ActionState<A>>,
action_state: Option<ResMut<ActionState<A>>>,
) {
if let Some(mut action_state) = action_state {
action_state.swap_to_update_state();
}
for mut action_state in query.iter_mut() {
action_state.swap_to_update_state();
}
}
pub fn swap_to_fixed_update<A: Actionlike>(
mut query: Query<&mut ActionState<A>>,
action_state: Option<ResMut<ActionState<A>>>,
) {
if let Some(mut action_state) = action_state {
action_state.swap_to_fixed_update_state();
}
for mut action_state in query.iter_mut() {
action_state.swap_to_fixed_update_state();
}
}
pub fn tick_action_state<A: Actionlike>(
mut query: Query<&mut ActionState<A>>,
action_state: Option<ResMut<ActionState<A>>>,
time: Res<Time<Real>>,
mut stored_previous_instant: Local<Option<Instant>>,
) {
let current_instant = time.last_update().unwrap_or_else(|| time.startup());
let previous_instant = stored_previous_instant.unwrap_or_else(|| time.startup());
if let Some(mut action_state) = action_state {
action_state.tick(current_instant, previous_instant);
}
for mut action_state in query.iter_mut() {
action_state.tick(current_instant, previous_instant);
}
*stored_previous_instant = time.last_update();
}
#[cfg(feature = "mouse")]
pub fn accumulate_mouse_movement(
mut mouse_motion: ResMut<AccumulatedMouseMovement>,
mut events: EventReader<MouseMotion>,
) {
mouse_motion.reset();
for event in events.read() {
mouse_motion.accumulate(event);
}
}
#[cfg(feature = "mouse")]
pub fn accumulate_mouse_scroll(
mut mouse_scroll: ResMut<AccumulatedMouseScroll>,
mut events: EventReader<MouseWheel>,
) {
mouse_scroll.reset();
for event in events.read() {
mouse_scroll.accumulate(event);
}
}
pub fn update_action_state<A: Actionlike>(
input_store: Res<CentralInputStore>,
clash_strategy: Res<ClashStrategy>,
gamepads: Res<Gamepads>,
action_state: Option<ResMut<ActionState<A>>>,
input_map: Option<Res<InputMap<A>>>,
mut query: Query<(&mut ActionState<A>, &InputMap<A>)>,
) {
let resources = input_map
.zip(action_state)
.map(|(input_map, action_state)| (Mut::from(action_state), input_map.into_inner()));
for (mut action_state, input_map) in query.iter_mut().chain(resources) {
action_state.update(input_map.process_actions(&gamepads, &input_store, *clash_strategy));
}
}
#[cfg(any(feature = "egui", feature = "ui"))]
pub fn filter_captured_input(
mut mouse_buttons: ResMut<bevy::input::ButtonInput<bevy::input::mouse::MouseButton>>,
#[cfg(feature = "ui")] interactions: Query<&bevy::ui::Interaction>,
#[cfg(feature = "egui")] mut keycodes: ResMut<
bevy::input::ButtonInput<bevy::input::keyboard::KeyCode>,
>,
#[cfg(feature = "egui")] mut egui_query: Query<&'static mut bevy_egui::EguiContext>,
) {
#[cfg(feature = "ui")]
if interactions
.iter()
.any(|&interaction| interaction != bevy::ui::Interaction::None)
{
mouse_buttons.clear();
}
#[cfg(feature = "egui")]
for mut egui_context in egui_query.iter_mut() {
if egui_context.get_mut().wants_pointer_input() {
mouse_buttons.clear();
}
if egui_context.get_mut().wants_keyboard_input() {
keycodes.clear();
}
}
}
pub fn generate_action_diffs<A: Actionlike>(
global_action_state: Option<Res<ActionState<A>>>,
action_state_query: Query<(Entity, &ActionState<A>)>,
mut previous_action_state: Local<SummarizedActionState<A>>,
mut action_diff_events: EventWriter<ActionDiffEvent<A>>,
) {
let current_action_state =
SummarizedActionState::summarize(global_action_state, action_state_query);
current_action_state.send_diffs(&previous_action_state, &mut action_diff_events);
dbg!(&previous_action_state, ¤t_action_state);
*previous_action_state = current_action_state;
}
pub fn release_on_input_map_removed<A: Actionlike>(
mut removed_components: RemovedComponents<InputMap<A>>,
input_map_resource: Option<ResMut<InputMap<A>>>,
action_state_resource: Option<ResMut<ActionState<A>>>,
mut input_map_resource_existed: Local<bool>,
mut action_state_query: Query<&mut ActionState<A>>,
) {
let mut iter = action_state_query.iter_many_mut(removed_components.read());
while let Some(mut action_state) = iter.fetch_next() {
action_state.reset_all();
}
if input_map_resource.is_some() {
*input_map_resource_existed = true;
} else if *input_map_resource_existed {
if let Some(mut action_state) = action_state_resource {
action_state.reset_all();
}
*input_map_resource_existed = false;
}
}
pub fn clear_central_input_store(mut input_store: ResMut<CentralInputStore>) {
input_store.clear();
}