11use bevy_utils:: HashSet ;
22use std:: hash:: Hash ;
33
4- /// A "press-able" input of type `T`
4+ // unused import, but needed for intra doc link to work
5+ #[ allow( unused_imports) ]
6+ use bevy_ecs:: schedule:: State ;
7+
8+ /// A "press-able" input of type `T`.
9+ ///
10+ /// This type can be used as a resource to keep the current state of an input, by reacting to
11+ /// events from the input. For a given input value:
12+ ///
13+ /// * [`Input::pressed`] will return `true` between a press and a release event.
14+ /// * [`Input::just_pressed`] will return `true` for one frame after a press event.
15+ /// * [`Input::just_released`] will return `true` for one frame after a release event.
16+ ///
17+ /// In case multiple systems are checking for [`Input::just_pressed`] or [`Input::just_released`]
18+ /// but only one should react, for example in the case of triggering
19+ /// [`State`] change, you should consider clearing the input state, either by:
20+ ///
21+ /// * Using [`Input::just_pressed_and_clear`] or [`Input::just_released_and_clear`] instead.
22+ /// * Calling [`Input::clear`] or [`Input::reset`] immediately after the state change.
23+ ///
24+ /// ## Notes when adding this resource for a new input type
25+ ///
26+ /// When adding this resource for a new input type, you should:
27+ ///
28+ /// * Call the [`Input::press`] method for each press event.
29+ /// * Call the [`Input::release`] method for each release event.
30+ /// * Call the [`Input::clear`] method at each frame start, before processing events.
531#[ derive( Debug ) ]
632pub struct Input < T > {
733 pressed : HashSet < T > ,
@@ -23,6 +49,7 @@ impl<T> Input<T>
2349where
2450 T : Copy + Eq + Hash ,
2551{
52+ /// Register a press for input `input`.
2653 pub fn press ( & mut self , input : T ) {
2754 if !self . pressed ( input) {
2855 self . just_pressed . insert ( input) ;
@@ -31,42 +58,65 @@ where
3158 self . pressed . insert ( input) ;
3259 }
3360
61+ /// Check if `input` has been pressed.
3462 pub fn pressed ( & self , input : T ) -> bool {
3563 self . pressed . contains ( & input)
3664 }
3765
66+ /// Register a release for input `input`.
3867 pub fn release ( & mut self , input : T ) {
3968 self . pressed . remove ( & input) ;
4069 self . just_released . insert ( input) ;
4170 }
4271
72+ /// Check if `input` has been just pressed.
4373 pub fn just_pressed ( & self , input : T ) -> bool {
4474 self . just_pressed . contains ( & input)
4575 }
4676
77+ /// Clear the "just pressed" state of `input`. Future calls to [`Input::just_pressed`] for the given
78+ /// input will return false until a new press event occurs.
79+ /// Returns true if `input` is currently "just pressed"
80+ pub fn clear_just_pressed ( & mut self , input : T ) -> bool {
81+ self . just_pressed . remove ( & input)
82+ }
83+
84+ /// Check if `input` has been just released.
4785 pub fn just_released ( & self , input : T ) -> bool {
4886 self . just_released . contains ( & input)
4987 }
5088
89+ /// Clear the "just released" state of `input`. Future calls to [`Input::just_released`] for the given
90+ /// input will return false until a new release event occurs.
91+ /// Returns true if `input` is currently "just released"
92+ pub fn clear_just_released ( & mut self , input : T ) -> bool {
93+ self . just_released . remove ( & input)
94+ }
95+
96+ /// Reset all status for input `input`.
5197 pub fn reset ( & mut self , input : T ) {
5298 self . pressed . remove ( & input) ;
5399 self . just_pressed . remove ( & input) ;
54100 self . just_released . remove ( & input) ;
55101 }
56102
57- pub fn update ( & mut self ) {
103+ /// Clear just pressed and just released information.
104+ pub fn clear ( & mut self ) {
58105 self . just_pressed . clear ( ) ;
59106 self . just_released . clear ( ) ;
60107 }
61108
109+ /// List all inputs that are pressed.
62110 pub fn get_pressed ( & self ) -> impl ExactSizeIterator < Item = & T > {
63111 self . pressed . iter ( )
64112 }
65113
114+ /// List all inputs that are just pressed.
66115 pub fn get_just_pressed ( & self ) -> impl ExactSizeIterator < Item = & T > {
67116 self . just_pressed . iter ( )
68117 }
69118
119+ /// List all inputs that are just released.
70120 pub fn get_just_released ( & self ) -> impl ExactSizeIterator < Item = & T > {
71121 self . just_released . iter ( )
72122 }
@@ -100,8 +150,8 @@ mod test {
100150 assert ! ( input. pressed( DummyInput :: Input1 ) ) ;
101151 assert ! ( input. pressed( DummyInput :: Input2 ) ) ;
102152
103- // Update the `Input` and check press state
104- input. update ( ) ;
153+ // Clear the `input`, removing just pressed and just released
154+ input. clear ( ) ;
105155
106156 // Check if they're marked "just pressed"
107157 assert ! ( !input. just_pressed( DummyInput :: Input1 ) ) ;
@@ -124,9 +174,8 @@ mod test {
124174 assert ! ( !input. pressed( DummyInput :: Input1 ) ) ;
125175 assert ! ( !input. pressed( DummyInput :: Input2 ) ) ;
126176
127- // Update the `Input` and check for removal from `just_released`
128-
129- input. update ( ) ;
177+ // Clear the `Input` and check for removal from `just_released`
178+ input. clear ( ) ;
130179
131180 // Check that they're not incorrectly marked as just released
132181 assert ! ( !input. just_released( DummyInput :: Input1 ) ) ;
0 commit comments