bevy_enhanced_input/condition.rs
1/*!
2Instead of hardcoded states like "pressed" or "released", all actions use an abstract [`TriggerState`] component
3(which is a required component of [`Action<C>`]). Its meaning depends on the assigned [input conditions](crate::condition),
4which determine when the action is triggered. This allows you to define flexible behaviors, such as "hold for 1 second".
5
6Input conditions are components that implement [`InputCondition`] trait. Similar to modifiers, you can attach them to
7both actions and bindings. They also evaluated during [`EnhancedInputSystems::Update`] right after modifiers in their insertion
8order and update [`TriggerState`] on the associated action entity.
9
10If no conditions are attached, the action behaves like with [`Down`] condition with a zero actuation threshold,
11meaning it will trigger on any non-zero input value.
12
13# Examples
14
15```
16use bevy::prelude::*;
17use bevy_enhanced_input::prelude::*;
18
19#[derive(Component)]
20struct Player;
21
22#[derive(InputAction)]
23#[action_output(bool)]
24struct Jump;
25
26#[derive(InputAction)]
27#[action_output(bool)]
28struct Fire;
29
30let mut world = World::new();
31world.spawn((
32 Player,
33 actions!(Player[
34 (
35 // The action will trigger only if held for 1 second.
36 Action::<Jump>::new(),
37 Hold::new(1.0),
38 bindings![KeyCode::Space, GamepadButton::South],
39 ),
40 (
41 Action::<Fire>::new(),
42 Pulse::new(0.5), // The action will trigger every 0.5 seconds while held.
43 bindings![
44 (GamepadButton::RightTrigger2, Down::new(0.3)), // Additionally the right trigger only counts if its value is greater than 0.3.
45 MouseButton::Left,
46 ]
47 ),
48 ])
49));
50```
51*/
52
53pub mod block_by;
54pub mod chord;
55pub mod combo;
56pub mod cooldown;
57pub mod down;
58pub mod fns;
59pub mod hold;
60pub mod hold_and_release;
61pub mod press;
62pub mod pulse;
63pub mod release;
64pub mod tap;
65pub mod toggle;
66
67use core::fmt::Debug;
68
69use crate::prelude::*;
70
71/// Default actuation threshold for all conditions.
72pub const DEFAULT_ACTUATION: f32 = 0.5;
73
74/// Defines how input activates.
75///
76/// Conditions analyze the input, checking for minimum actuation values
77/// and validating patterns like short taps, prolonged holds, or the typical "press"
78/// or "release" events.
79///
80/// Can be attached both to bindings and actions.
81///
82/// If you create a custom condition, it needs to be registered using
83/// [`InputConditionAppExt::add_input_condition`].
84pub trait InputCondition: Debug {
85 /// Returns calculates state.
86 ///
87 /// `actions` is a state of other actions within the currently evaluating context.
88 fn evaluate(
89 &mut self,
90 actions: &ActionsQuery,
91 time: &ContextTime,
92 value: ActionValue,
93 ) -> TriggerState;
94
95 /// Returns how the condition is combined with others.
96 fn kind(&self) -> ConditionKind {
97 ConditionKind::Explicit
98 }
99}
100
101/// Determines how a condition contributes to the final [`TriggerState`].
102///
103/// If no conditions are provided, the state will be set to [`TriggerState::Fired`]
104/// on any non-zero value, functioning similarly to a [`Down`] condition
105/// with a zero actuation threshold.
106///
107/// For details about how actions are combined, see [`Actions`].
108pub enum ConditionKind {
109 /// The most significant [`TriggerState`] from all explicit conditions will be the
110 /// resulting state.
111 Explicit,
112 /// Like [`Self::Explicit`], but [`TriggerState::Fired`] will be set only if all
113 /// implicit conditions return it.
114 ///
115 /// Otherwise, the most significant state will be capped at [`TriggerState::Ongoing`].
116 Implicit,
117 /// Any blocking condition that returns [`TriggerState::None`] will override
118 /// the state with [`TriggerState::None`].
119 ///
120 /// Doesn't contribute to the state on its own.
121 Blocker,
122}