leafwing_input_manager/
common_conditions.rs

1//! Run conditions for actions.
2
3use crate::{prelude::ActionState, Actionlike};
4use bevy::{
5    ecs::system::{Single, SystemParam},
6    log::warn,
7    prelude::Res,
8};
9
10/// A system parameter that fetches the [`ActionState`] either from a resource or from a component. If both exist, the resource takes precedence.
11#[derive(SystemParam)]
12pub struct ActionStateParam<'w, 's, A>
13where
14    A: Actionlike + Clone,
15{
16    action_state_resource: Option<Res<'w, ActionState<A>>>,
17    action_state_component: Option<Single<'w, 's, &'static ActionState<A>>>,
18}
19impl<'w, 's, A> ActionStateParam<'w, 's, A>
20where
21    A: Actionlike + Clone,
22{
23    fn as_ref(&self) -> Option<&ActionState<A>> {
24        if self.action_state_resource.is_some() {
25            self.action_state_resource.as_deref()
26        } else if self.action_state_component.is_some() {
27            Some(self.action_state_component.as_ref().unwrap())
28        } else {
29            let type_name = std::any::type_name::<A>();
30            warn!("No ActionState found for {type_name}. Please ensure that an ActionState resource is added, or that an InputMap component exists to provide an ActionState.");
31            None
32        }
33    }
34}
35
36/// Stateful run condition that can be toggled via an action press using [`ActionState::just_pressed`].
37pub fn action_toggle_active<A>(
38    default: bool,
39    action: A,
40) -> impl for<'w, 's> FnMut(ActionStateParam<'w, 's, A>) -> bool
41where
42    A: Actionlike + Clone,
43{
44    move |action_state_params| {
45        action_state_params
46            .as_ref()
47            .is_some_and(|state| state.pressed(&action))
48            || default
49    }
50}
51
52/// Run condition that is active if [`ActionState::pressed`] is true for the given action.
53pub fn action_pressed<A>(action: A) -> impl for<'w, 's> FnMut(ActionStateParam<'w, 's, A>) -> bool
54where
55    A: Actionlike + Clone,
56{
57    move |action_state_params| {
58        action_state_params
59            .as_ref()
60            .is_some_and(|state| state.pressed(&action))
61    }
62}
63
64/// Run condition that is active if [`ActionState::just_pressed`] is true for the given action.
65pub fn action_just_pressed<A>(
66    action: A,
67) -> impl for<'w, 's> FnMut(ActionStateParam<'w, 's, A>) -> bool
68where
69    A: Actionlike + Clone,
70{
71    move |action_state_params| {
72        action_state_params
73            .as_ref()
74            .is_some_and(|state| state.just_pressed(&action))
75    }
76}
77
78/// Run condition that is active if [`ActionState::just_released`] is true for the given action.
79pub fn action_just_released<A>(
80    action: A,
81) -> impl for<'w, 's> FnMut(ActionStateParam<'w, 's, A>) -> bool
82where
83    A: Actionlike + Clone,
84{
85    move |action_state_params| {
86        action_state_params
87            .as_ref()
88            .is_some_and(|state| state.just_released(&action))
89    }
90}