2023-08-23 12:44:49 +00:00
//! The generic input type.
Make `Resource` trait opt-in, requiring `#[derive(Resource)]` V2 (#5577)
*This PR description is an edited copy of #5007, written by @alice-i-cecile.*
# Objective
Follow-up to https://github.com/bevyengine/bevy/pull/2254. The `Resource` trait currently has a blanket implementation for all types that meet its bounds.
While ergonomic, this results in several drawbacks:
* it is possible to make confusing, silent mistakes such as inserting a function pointer (Foo) rather than a value (Foo::Bar) as a resource
* it is challenging to discover if a type is intended to be used as a resource
* we cannot later add customization options (see the [RFC](https://github.com/bevyengine/rfcs/blob/main/rfcs/27-derive-component.md) for the equivalent choice for Component).
* dependencies can use the same Rust type as a resource in invisibly conflicting ways
* raw Rust types used as resources cannot preserve privacy appropriately, as anyone able to access that type can read and write to internal values
* we cannot capture a definitive list of possible resources to display to users in an editor
## Notes to reviewers
* Review this commit-by-commit; there's effectively no back-tracking and there's a lot of churn in some of these commits.
*ira: My commits are not as well organized :')*
* I've relaxed the bound on Local to Send + Sync + 'static: I don't think these concerns apply there, so this can keep things simple. Storing e.g. a u32 in a Local is fine, because there's a variable name attached explaining what it does.
* I think this is a bad place for the Resource trait to live, but I've left it in place to make reviewing easier. IMO that's best tackled with https://github.com/bevyengine/bevy/issues/4981.
## Changelog
`Resource` is no longer automatically implemented for all matching types. Instead, use the new `#[derive(Resource)]` macro.
## Migration Guide
Add `#[derive(Resource)]` to all types you are using as a resource.
If you are using a third party type as a resource, wrap it in a tuple struct to bypass orphan rules. Consider deriving `Deref` and `DerefMut` to improve ergonomics.
`ClearColor` no longer implements `Component`. Using `ClearColor` as a component in 0.8 did nothing.
Use the `ClearColorConfig` in the `Camera3d` and `Camera2d` components instead.
Co-authored-by: Alice <alice.i.cecile@gmail.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: devil-ira <justthecooldude@gmail.com>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-08-08 21:36:35 +00:00
use bevy_ecs ::system ::Resource ;
2020-08-29 00:08:51 +00:00
use bevy_utils ::HashSet ;
2024-09-27 00:59:59 +00:00
use core ::hash ::Hash ;
#[ cfg(feature = " bevy_reflect " ) ]
use {
bevy_ecs ::reflect ::ReflectResource ,
bevy_reflect ::{ std_traits ::ReflectDefault , Reflect } ,
} ;
2020-06-05 05:48:53 +00:00
2021-04-13 03:13:48 +00:00
/// A "press-able" input of type `T`.
///
2022-04-25 13:16:21 +00:00
/// ## Usage
///
2021-04-13 03:13:48 +00:00
/// This type can be used as a resource to keep the current state of an input, by reacting to
/// events from the input. For a given input value:
///
2023-12-06 20:32:34 +00:00
/// * [`ButtonInput::pressed`] will return `true` between a press and a release event.
/// * [`ButtonInput::just_pressed`] will return `true` for one frame after a press event.
/// * [`ButtonInput::just_released`] will return `true` for one frame after a release event.
2021-04-13 03:13:48 +00:00
///
2022-04-25 13:16:21 +00:00
/// ## Multiple systems
///
2023-12-06 20:32:34 +00:00
/// In case multiple systems are checking for [`ButtonInput::just_pressed`] or [`ButtonInput::just_released`]
Separate state crate (#13216)
# Objective
Extracts the state mechanisms into a new crate called "bevy_state".
This comes with a few goals:
- state wasn't really an inherent machinery of the ecs system, and so
keeping it within bevy_ecs felt forced
- by mixing it in with bevy_ecs, the maintainability of our more robust
state system was significantly compromised
moving state into a new crate makes it easier to encapsulate as it's own
feature, and easier to read and understand since it's no longer a
single, massive file.
## Solution
move the state-related elements from bevy_ecs to a new crate
## Testing
- Did you test these changes? If so, how? all the automated tests
migrated and passed, ran the pre-existing examples without changes to
validate.
---
## Migration Guide
Since bevy_state is now gated behind the `bevy_state` feature, projects
that use state but don't use the `default-features` will need to add
that feature flag.
Since it is no longer part of bevy_ecs, projects that use bevy_ecs
directly will need to manually pull in `bevy_state`, trigger the
StateTransition schedule, and handle any of the elements that bevy_app
currently sets up.
---------
Co-authored-by: Kristoffer Søholm <k.soeholm@gmail.com>
2024-05-09 18:06:05 +00:00
/// but only one should react, for example when modifying a
/// [`Resource`], you should consider clearing the input state, either by:
2021-04-13 03:13:48 +00:00
///
2023-12-06 20:32:34 +00:00
/// * Using [`ButtonInput::clear_just_pressed`] or [`ButtonInput::clear_just_released`] instead.
/// * Calling [`ButtonInput::clear`] or [`ButtonInput::reset`] immediately after the state change.
2021-04-13 03:13:48 +00:00
///
2024-03-10 23:00:20 +00:00
/// ## Performance
///
/// For all operations, the following conventions are used:
/// - **n** is the number of stored inputs.
/// - **m** is the number of input arguments passed to the method.
/// - **\***-suffix denotes an amortized cost.
/// - **~**-suffix denotes an expected cost.
///
/// See Rust's [std::collections doc on performance](https://doc.rust-lang.org/std/collections/index.html#performance) for more details on the conventions used here.
///
/// | **[`ButtonInput`] operations** | **Computational complexity** |
/// |-----------------------------------|------------------------------------|
2024-04-22 00:42:04 +00:00
/// | [`ButtonInput::any_just_pressed`] | *O*(m)~ |
/// | [`ButtonInput::any_just_released`] | *O*(m)~ |
/// | [`ButtonInput::any_pressed`] | *O*(m)~ |
2024-03-10 23:00:20 +00:00
/// | [`ButtonInput::get_just_pressed`] | *O*(n) |
/// | [`ButtonInput::get_just_released`] | *O*(n) |
/// | [`ButtonInput::get_pressed`] | *O*(n) |
/// | [`ButtonInput::just_pressed`] | *O*(1)~ |
/// | [`ButtonInput::just_released`] | *O*(1)~ |
/// | [`ButtonInput::pressed`] | *O*(1)~ |
/// | [`ButtonInput::press`] | *O*(1)~* |
/// | [`ButtonInput::release`] | *O*(1)~* |
/// | [`ButtonInput::release_all`] | *O*(n)~* |
/// | [`ButtonInput::clear_just_pressed`] | *O*(1)~ |
/// | [`ButtonInput::clear_just_released`] | *O*(1)~ |
/// | [`ButtonInput::reset_all`] | *O*(n) |
/// | [`ButtonInput::clear`] | *O*(n) |
///
2024-03-08 16:03:42 +00:00
/// ## Window focus
///
/// `ButtonInput<KeyCode>` is tied to window focus. For example, if the user holds a button
/// while the window loses focus, [`ButtonInput::just_released`] will be triggered. Similarly if the window
2024-09-30 18:24:36 +00:00
/// regains focus, [`ButtonInput::just_pressed`] will be triggered.
2024-03-08 16:03:42 +00:00
///
/// `ButtonInput<GamepadButton>` is independent of window focus.
///
2024-04-22 17:48:46 +00:00
/// ## Examples
///
/// Reading and checking against the current set of pressed buttons:
/// ```no_run
/// # use bevy_app::{App, NoopPluginGroup as DefaultPlugins, Update};
/// # use bevy_ecs::{prelude::{IntoSystemConfigs, Res, Resource, resource_changed}, schedule::Condition};
Implement gamepads as entities (#12770)
# Objective
- Significantly improve the ergonomics of gamepads and allow new
features
Gamepads are a bit unergonomic to work with, they use resources but
unlike other inputs, they are not limited to a single gamepad, to get
around this it uses an identifier (Gamepad) to interact with anything
causing all sorts of issues.
1. There are too many: Gamepads, GamepadSettings, GamepadInfo,
ButtonInput<T>, 2 Axis<T>.
2. ButtonInput/Axis generic methods become really inconvenient to use
e.g. any_pressed()
3. GamepadButton/Axis structs are unnecessary boilerplate:
```rust
for gamepad in gamepads.iter() {
if button_inputs.just_pressed(GamepadButton::new(gamepad, GamepadButtonType::South)) {
info!("{:?} just pressed South", gamepad);
} else if button_inputs.just_released(GamepadButton::new(gamepad, GamepadButtonType::South))
{
info!("{:?} just released South", gamepad);
}
}
```
4. Projects often need to create resources to store the selected gamepad
and have to manually check if their gamepad is still valid anyways.
- Previously attempted by #3419 and #12674
## Solution
- Implement gamepads as entities.
Using entities solves all the problems above and opens new
possibilities.
1. Reduce boilerplate and allows iteration
```rust
let is_pressed = gamepads_buttons.iter().any(|buttons| buttons.pressed(GamepadButtonType::South))
```
2. ButtonInput/Axis generic methods become ergonomic again
```rust
gamepad_buttons.any_just_pressed([GamepadButtonType::Start, GamepadButtonType::Select])
```
3. Reduces the number of public components significantly (Gamepad,
GamepadSettings, GamepadButtons, GamepadAxes)
4. Components are highly convenient. Gamepad optional features could now
be expressed naturally (`Option<Rumble> or Option<Gyro>`), allows devs
to attach their own components and filter them, so code like this
becomes possible:
```rust
fn move_player<const T: usize>(
player: Query<&Transform, With<Player<T>>>,
gamepads_buttons: Query<&GamepadButtons, With<Player<T>>>,
) {
if let Ok(gamepad_buttons) = gamepads_buttons.get_single() {
if gamepad_buttons.pressed(GamepadButtonType::South) {
// move player
}
}
}
```
---
## Follow-up
- [ ] Run conditions?
- [ ] Rumble component
# Changelog
## Added
TODO
## Changed
TODO
## Removed
TODO
## Migration Guide
TODO
---------
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2024-09-27 20:07:20 +00:00
/// # use bevy_input::{ButtonInput, prelude::{KeyCode, MouseButton}};
2024-04-22 17:48:46 +00:00
///
/// fn main() {
/// App::new()
/// .add_plugins(DefaultPlugins)
/// .add_systems(
/// Update,
/// print_mouse.run_if(resource_changed::<ButtonInput<MouseButton>>),
/// )
/// .add_systems(
/// Update,
/// print_keyboard.run_if(resource_changed::<ButtonInput<KeyCode>>),
/// )
/// .run();
/// }
///
/// fn print_mouse(mouse: Res<ButtonInput<MouseButton>>) {
/// println!("Mouse: {:?}", mouse.get_pressed().collect::<Vec<_>>());
/// }
///
/// fn print_keyboard(keyboard: Res<ButtonInput<KeyCode>>) {
/// if keyboard.any_pressed([KeyCode::ControlLeft, KeyCode::ControlRight])
/// && keyboard.any_pressed([KeyCode::AltLeft, KeyCode::AltRight])
/// && keyboard.any_pressed([KeyCode::ShiftLeft, KeyCode::ShiftRight])
/// && keyboard.any_pressed([KeyCode::SuperLeft, KeyCode::SuperRight])
/// && keyboard.pressed(KeyCode::KeyL)
/// {
/// println!("On Windows this opens LinkedIn.");
/// } else {
/// println!("keyboard: {:?}", keyboard.get_pressed().collect::<Vec<_>>());
/// }
/// }
/// ```
///
2022-04-25 13:16:21 +00:00
/// ## Note
2021-04-13 03:13:48 +00:00
///
/// When adding this resource for a new input type, you should:
///
2023-12-06 20:32:34 +00:00
/// * Call the [`ButtonInput::press`] method for each press event.
/// * Call the [`ButtonInput::release`] method for each release event.
/// * Call the [`ButtonInput::clear`] method at each frame start, before processing events.
2022-12-11 18:22:09 +00:00
///
/// Note: Calling `clear` from a [`ResMut`] will trigger change detection.
2023-01-11 15:41:54 +00:00
/// It may be preferable to use [`DetectChangesMut::bypass_change_detection`]
2022-12-11 18:22:09 +00:00
/// to avoid causing the resource to always be marked as changed.
///
2024-09-24 11:42:59 +00:00
/// [`ResMut`]: bevy_ecs::system::ResMut
/// [`DetectChangesMut::bypass_change_detection`]: bevy_ecs::change_detection::DetectChangesMut::bypass_change_detection
2024-07-08 01:09:07 +00:00
#[ derive(Debug, Clone, Resource) ]
2024-09-15 15:08:46 +00:00
#[ cfg_attr(feature = " bevy_reflect " , derive(Reflect), reflect(Default, Resource)) ]
2023-12-06 20:32:34 +00:00
pub struct ButtonInput < T : Copy + Eq + Hash + Send + Sync + 'static > {
2022-04-25 13:16:21 +00:00
/// A collection of every button that is currently being pressed.
2020-06-05 06:34:21 +00:00
pressed : HashSet < T > ,
2022-04-25 13:16:21 +00:00
/// A collection of every button that has just been pressed.
2020-06-05 06:34:21 +00:00
just_pressed : HashSet < T > ,
2022-04-25 13:16:21 +00:00
/// A collection of every button that has just been released.
2020-06-05 06:34:21 +00:00
just_released : HashSet < T > ,
2020-06-05 05:48:53 +00:00
}
2023-12-06 20:32:34 +00:00
impl < T : Copy + Eq + Hash + Send + Sync + 'static > Default for ButtonInput < T > {
2020-06-05 06:34:21 +00:00
fn default ( ) -> Self {
Self {
pressed : Default ::default ( ) ,
just_pressed : Default ::default ( ) ,
just_released : Default ::default ( ) ,
2020-06-05 05:48:53 +00:00
}
}
2020-06-05 06:34:21 +00:00
}
2020-06-05 05:48:53 +00:00
2023-12-06 20:32:34 +00:00
impl < T > ButtonInput < T >
2020-06-05 06:34:21 +00:00
where
2022-09-07 15:59:50 +00:00
T : Copy + Eq + Hash + Send + Sync + 'static ,
2020-06-05 06:34:21 +00:00
{
2022-04-25 13:16:21 +00:00
/// Registers a press for the given `input`.
2020-06-05 06:34:21 +00:00
pub fn press ( & mut self , input : T ) {
2022-03-29 22:39:16 +00:00
// Returns `true` if the `input` wasn't pressed.
if self . pressed . insert ( input ) {
2020-06-05 06:34:21 +00:00
self . just_pressed . insert ( input ) ;
}
2020-06-05 05:48:53 +00:00
}
2022-04-25 13:16:21 +00:00
/// Returns `true` if the `input` has been pressed.
2020-06-05 06:34:21 +00:00
pub fn pressed ( & self , input : T ) -> bool {
self . pressed . contains ( & input )
2020-06-05 05:48:53 +00:00
}
2022-04-25 13:16:21 +00:00
/// Returns `true` if any item in `inputs` has been pressed.
2021-09-01 21:21:41 +00:00
pub fn any_pressed ( & self , inputs : impl IntoIterator < Item = T > ) -> bool {
inputs . into_iter ( ) . any ( | it | self . pressed ( it ) )
}
2023-12-18 01:45:43 +00:00
/// Returns `true` if all items in `inputs` have been pressed.
pub fn all_pressed ( & self , inputs : impl IntoIterator < Item = T > ) -> bool {
inputs . into_iter ( ) . all ( | it | self . pressed ( it ) )
}
2022-04-25 13:16:21 +00:00
/// Registers a release for the given `input`.
2020-06-05 06:34:21 +00:00
pub fn release ( & mut self , input : T ) {
2022-03-29 22:39:16 +00:00
// Returns `true` if the `input` was pressed.
if self . pressed . remove ( & input ) {
2022-03-20 21:54:09 +00:00
self . just_released . insert ( input ) ;
}
2020-06-05 05:48:53 +00:00
}
2022-06-20 17:35:56 +00:00
/// Registers a release for all currently pressed inputs.
pub fn release_all ( & mut self ) {
// Move all items from pressed into just_released
self . just_released . extend ( self . pressed . drain ( ) ) ;
}
2024-03-23 01:26:03 +00:00
/// Returns `true` if the `input` has been pressed during the current frame.
///
/// Note: This function does not imply information regarding the current state of [`ButtonInput::pressed`] or [`ButtonInput::just_released`].
2020-06-05 06:34:21 +00:00
pub fn just_pressed ( & self , input : T ) -> bool {
self . just_pressed . contains ( & input )
2020-06-05 05:48:53 +00:00
}
2024-03-23 01:26:03 +00:00
/// Returns `true` if any item in `inputs` has been pressed during the current frame.
2021-09-01 21:21:41 +00:00
pub fn any_just_pressed ( & self , inputs : impl IntoIterator < Item = T > ) -> bool {
inputs . into_iter ( ) . any ( | it | self . just_pressed ( it ) )
}
2022-04-25 13:16:21 +00:00
/// Clears the `just_pressed` state of the `input` and returns `true` if the `input` has just been pressed.
///
2023-12-06 20:32:34 +00:00
/// Future calls to [`ButtonInput::just_pressed`] for the given input will return false until a new press event occurs.
2021-04-13 03:13:48 +00:00
pub fn clear_just_pressed ( & mut self , input : T ) -> bool {
self . just_pressed . remove ( & input )
}
2024-03-23 01:26:03 +00:00
/// Returns `true` if the `input` has been released during the current frame.
///
/// Note: This function does not imply information regarding the current state of [`ButtonInput::pressed`] or [`ButtonInput::just_pressed`].
2020-06-05 06:34:21 +00:00
pub fn just_released ( & self , input : T ) -> bool {
self . just_released . contains ( & input )
}
2020-06-05 05:48:53 +00:00
2022-04-25 13:16:21 +00:00
/// Returns `true` if any item in `inputs` has just been released.
2021-09-01 21:21:41 +00:00
pub fn any_just_released ( & self , inputs : impl IntoIterator < Item = T > ) -> bool {
2024-11-19 00:00:16 +00:00
inputs . into_iter ( ) . any ( | input | self . just_released ( input ) )
}
/// Returns `true` if all items in `inputs` have just been released.
pub fn all_just_released ( & self , inputs : impl IntoIterator < Item = T > ) -> bool {
inputs . into_iter ( ) . all ( | input | self . just_released ( input ) )
}
/// Returns `true` if all items in `inputs` have been just pressed.
pub fn all_just_pressed ( & self , inputs : impl IntoIterator < Item = T > ) -> bool {
inputs . into_iter ( ) . all ( | input | self . just_pressed ( input ) )
2021-09-01 21:21:41 +00:00
}
2022-04-25 13:16:21 +00:00
/// Clears the `just_released` state of the `input` and returns `true` if the `input` has just been released.
///
2023-12-06 20:32:34 +00:00
/// Future calls to [`ButtonInput::just_released`] for the given input will return false until a new release event occurs.
2021-04-13 03:13:48 +00:00
pub fn clear_just_released ( & mut self , input : T ) -> bool {
self . just_released . remove ( & input )
}
2022-04-25 13:16:21 +00:00
/// Clears the `pressed`, `just_pressed` and `just_released` data of the `input`.
2020-09-18 21:43:47 +00:00
pub fn reset ( & mut self , input : T ) {
self . pressed . remove ( & input ) ;
self . just_pressed . remove ( & input ) ;
self . just_released . remove ( & input ) ;
}
2022-06-20 18:31:46 +00:00
/// Clears the `pressed`, `just_pressed`, and `just_released` data for every input.
///
2023-12-06 20:32:34 +00:00
/// See also [`ButtonInput::clear`] for simulating elapsed time steps.
2022-06-20 18:31:46 +00:00
pub fn reset_all ( & mut self ) {
self . pressed . clear ( ) ;
self . just_pressed . clear ( ) ;
self . just_released . clear ( ) ;
}
2022-04-25 13:16:21 +00:00
/// Clears the `just pressed` and `just released` data for every input.
2022-06-20 18:31:46 +00:00
///
2023-12-06 20:32:34 +00:00
/// See also [`ButtonInput::reset_all`] for a full reset.
2021-04-13 03:13:48 +00:00
pub fn clear ( & mut self ) {
2020-06-05 06:34:21 +00:00
self . just_pressed . clear ( ) ;
self . just_released . clear ( ) ;
2020-06-05 05:48:53 +00:00
}
2020-09-04 00:32:17 +00:00
2022-04-25 13:16:21 +00:00
/// An iterator visiting every pressed input in arbitrary order.
2020-09-04 00:32:17 +00:00
pub fn get_pressed ( & self ) -> impl ExactSizeIterator < Item = & T > {
self . pressed . iter ( )
}
2022-04-25 13:16:21 +00:00
/// An iterator visiting every just pressed input in arbitrary order.
2024-03-23 01:26:03 +00:00
///
/// Note: Returned elements do not imply information regarding the current state of [`ButtonInput::pressed`] or [`ButtonInput::just_released`].
2020-09-04 00:32:17 +00:00
pub fn get_just_pressed ( & self ) -> impl ExactSizeIterator < Item = & T > {
self . just_pressed . iter ( )
}
2022-04-25 13:16:21 +00:00
/// An iterator visiting every just released input in arbitrary order.
2024-03-23 01:26:03 +00:00
///
/// Note: Returned elements do not imply information regarding the current state of [`ButtonInput::pressed`] or [`ButtonInput::just_pressed`].
2020-09-04 00:32:17 +00:00
pub fn get_just_released ( & self ) -> impl ExactSizeIterator < Item = & T > {
self . just_released . iter ( )
}
2020-06-05 05:48:53 +00:00
}
2020-12-01 06:58:49 +00:00
#[ cfg(test) ]
mod test {
2023-12-06 20:32:34 +00:00
use crate ::ButtonInput ;
2022-04-25 13:16:24 +00:00
2023-12-06 20:32:34 +00:00
/// Used for testing the functionality of [`ButtonInput`].
2024-07-08 01:09:07 +00:00
#[ derive(Copy, Clone, Eq, PartialEq, Hash) ]
2022-04-25 13:16:24 +00:00
enum DummyInput {
Input1 ,
Input2 ,
}
#[ test ]
fn test_press ( ) {
2023-12-06 20:32:34 +00:00
let mut input = ButtonInput ::default ( ) ;
2022-04-25 13:16:24 +00:00
assert! ( ! input . pressed . contains ( & DummyInput ::Input1 ) ) ;
assert! ( ! input . just_pressed . contains ( & DummyInput ::Input1 ) ) ;
input . press ( DummyInput ::Input1 ) ;
assert! ( input . just_pressed . contains ( & DummyInput ::Input1 ) ) ;
assert! ( input . pressed . contains ( & DummyInput ::Input1 ) ) ;
}
#[ test ]
fn test_pressed ( ) {
2023-12-06 20:32:34 +00:00
let mut input = ButtonInput ::default ( ) ;
2022-04-25 13:16:24 +00:00
assert! ( ! input . pressed ( DummyInput ::Input1 ) ) ;
input . press ( DummyInput ::Input1 ) ;
assert! ( input . pressed ( DummyInput ::Input1 ) ) ;
}
#[ test ]
fn test_any_pressed ( ) {
2023-12-06 20:32:34 +00:00
let mut input = ButtonInput ::default ( ) ;
2022-04-25 13:16:24 +00:00
assert! ( ! input . any_pressed ( [ DummyInput ::Input1 ] ) ) ;
assert! ( ! input . any_pressed ( [ DummyInput ::Input2 ] ) ) ;
assert! ( ! input . any_pressed ( [ DummyInput ::Input1 , DummyInput ::Input2 ] ) ) ;
input . press ( DummyInput ::Input1 ) ;
assert! ( input . any_pressed ( [ DummyInput ::Input1 ] ) ) ;
assert! ( ! input . any_pressed ( [ DummyInput ::Input2 ] ) ) ;
assert! ( input . any_pressed ( [ DummyInput ::Input1 , DummyInput ::Input2 ] ) ) ;
}
2023-12-18 01:45:43 +00:00
#[ test ]
fn test_all_pressed ( ) {
let mut input = ButtonInput ::default ( ) ;
assert! ( ! input . all_pressed ( [ DummyInput ::Input1 ] ) ) ;
assert! ( ! input . all_pressed ( [ DummyInput ::Input2 ] ) ) ;
assert! ( ! input . all_pressed ( [ DummyInput ::Input1 , DummyInput ::Input2 ] ) ) ;
input . press ( DummyInput ::Input1 ) ;
assert! ( input . all_pressed ( [ DummyInput ::Input1 ] ) ) ;
assert! ( ! input . all_pressed ( [ DummyInput ::Input1 , DummyInput ::Input2 ] ) ) ;
input . press ( DummyInput ::Input2 ) ;
assert! ( input . all_pressed ( [ DummyInput ::Input1 , DummyInput ::Input2 ] ) ) ;
}
2022-04-25 13:16:24 +00:00
#[ test ]
fn test_release ( ) {
2023-12-06 20:32:34 +00:00
let mut input = ButtonInput ::default ( ) ;
2022-04-25 13:16:24 +00:00
input . press ( DummyInput ::Input1 ) ;
assert! ( input . pressed . contains ( & DummyInput ::Input1 ) ) ;
assert! ( ! input . just_released . contains ( & DummyInput ::Input1 ) ) ;
input . release ( DummyInput ::Input1 ) ;
assert! ( ! input . pressed . contains ( & DummyInput ::Input1 ) ) ;
assert! ( input . just_released . contains ( & DummyInput ::Input1 ) ) ;
}
2022-06-20 17:35:56 +00:00
#[ test ]
fn test_release_all ( ) {
2023-12-06 20:32:34 +00:00
let mut input = ButtonInput ::default ( ) ;
2022-06-20 17:35:56 +00:00
input . press ( DummyInput ::Input1 ) ;
input . press ( DummyInput ::Input2 ) ;
input . release_all ( ) ;
assert! ( input . pressed . is_empty ( ) ) ;
assert! ( input . just_released . contains ( & DummyInput ::Input1 ) ) ;
assert! ( input . just_released . contains ( & DummyInput ::Input2 ) ) ;
}
2022-04-25 13:16:24 +00:00
#[ test ]
fn test_just_pressed ( ) {
2023-12-06 20:32:34 +00:00
let mut input = ButtonInput ::default ( ) ;
2022-04-25 13:16:24 +00:00
assert! ( ! input . just_pressed ( DummyInput ::Input1 ) ) ;
input . press ( DummyInput ::Input1 ) ;
assert! ( input . just_pressed ( DummyInput ::Input1 ) ) ;
}
#[ test ]
fn test_any_just_pressed ( ) {
2023-12-06 20:32:34 +00:00
let mut input = ButtonInput ::default ( ) ;
2022-04-25 13:16:24 +00:00
assert! ( ! input . any_just_pressed ( [ DummyInput ::Input1 ] ) ) ;
assert! ( ! input . any_just_pressed ( [ DummyInput ::Input2 ] ) ) ;
assert! ( ! input . any_just_pressed ( [ DummyInput ::Input1 , DummyInput ::Input2 ] ) ) ;
input . press ( DummyInput ::Input1 ) ;
assert! ( input . any_just_pressed ( [ DummyInput ::Input1 ] ) ) ;
assert! ( ! input . any_just_pressed ( [ DummyInput ::Input2 ] ) ) ;
assert! ( input . any_just_pressed ( [ DummyInput ::Input1 , DummyInput ::Input2 ] ) ) ;
}
#[ test ]
fn test_clear_just_pressed ( ) {
2023-12-06 20:32:34 +00:00
let mut input = ButtonInput ::default ( ) ;
2022-04-25 13:16:24 +00:00
input . press ( DummyInput ::Input1 ) ;
assert! ( input . just_pressed ( DummyInput ::Input1 ) ) ;
input . clear_just_pressed ( DummyInput ::Input1 ) ;
assert! ( ! input . just_pressed ( DummyInput ::Input1 ) ) ;
}
#[ test ]
fn test_just_released ( ) {
2023-12-06 20:32:34 +00:00
let mut input = ButtonInput ::default ( ) ;
2022-04-25 13:16:24 +00:00
input . press ( DummyInput ::Input1 ) ;
assert! ( ! input . just_released ( DummyInput ::Input1 ) ) ;
input . release ( DummyInput ::Input1 ) ;
assert! ( input . just_released ( DummyInput ::Input1 ) ) ;
}
#[ test ]
fn test_any_just_released ( ) {
2023-12-06 20:32:34 +00:00
let mut input = ButtonInput ::default ( ) ;
2022-04-25 13:16:24 +00:00
input . press ( DummyInput ::Input1 ) ;
assert! ( ! input . any_just_released ( [ DummyInput ::Input1 ] ) ) ;
assert! ( ! input . any_just_released ( [ DummyInput ::Input2 ] ) ) ;
assert! ( ! input . any_just_released ( [ DummyInput ::Input1 , DummyInput ::Input2 ] ) ) ;
input . release ( DummyInput ::Input1 ) ;
assert! ( input . any_just_released ( [ DummyInput ::Input1 ] ) ) ;
assert! ( ! input . any_just_released ( [ DummyInput ::Input2 ] ) ) ;
assert! ( input . any_just_released ( [ DummyInput ::Input1 , DummyInput ::Input2 ] ) ) ;
}
#[ test ]
fn test_clear_just_released ( ) {
2023-12-06 20:32:34 +00:00
let mut input = ButtonInput ::default ( ) ;
2022-04-25 13:16:24 +00:00
input . press ( DummyInput ::Input1 ) ;
input . release ( DummyInput ::Input1 ) ;
assert! ( input . just_released ( DummyInput ::Input1 ) ) ;
input . clear_just_released ( DummyInput ::Input1 ) ;
assert! ( ! input . just_released ( DummyInput ::Input1 ) ) ;
}
#[ test ]
fn test_reset ( ) {
2023-12-06 20:32:34 +00:00
let mut input = ButtonInput ::default ( ) ;
2022-04-25 13:16:24 +00:00
// Pressed
input . press ( DummyInput ::Input1 ) ;
assert! ( input . pressed ( DummyInput ::Input1 ) ) ;
assert! ( input . just_pressed ( DummyInput ::Input1 ) ) ;
assert! ( ! input . just_released ( DummyInput ::Input1 ) ) ;
input . reset ( DummyInput ::Input1 ) ;
assert! ( ! input . pressed ( DummyInput ::Input1 ) ) ;
assert! ( ! input . just_pressed ( DummyInput ::Input1 ) ) ;
assert! ( ! input . just_released ( DummyInput ::Input1 ) ) ;
// Released
input . press ( DummyInput ::Input1 ) ;
input . release ( DummyInput ::Input1 ) ;
assert! ( ! input . pressed ( DummyInput ::Input1 ) ) ;
assert! ( input . just_pressed ( DummyInput ::Input1 ) ) ;
assert! ( input . just_released ( DummyInput ::Input1 ) ) ;
input . reset ( DummyInput ::Input1 ) ;
assert! ( ! input . pressed ( DummyInput ::Input1 ) ) ;
assert! ( ! input . just_pressed ( DummyInput ::Input1 ) ) ;
assert! ( ! input . just_released ( DummyInput ::Input1 ) ) ;
}
2020-12-01 06:58:49 +00:00
2022-06-20 18:31:46 +00:00
#[ test ]
fn test_reset_all ( ) {
2023-12-06 20:32:34 +00:00
let mut input = ButtonInput ::default ( ) ;
2022-06-20 18:31:46 +00:00
input . press ( DummyInput ::Input1 ) ;
input . press ( DummyInput ::Input2 ) ;
input . release ( DummyInput ::Input2 ) ;
assert! ( input . pressed . contains ( & DummyInput ::Input1 ) ) ;
assert! ( input . just_pressed . contains ( & DummyInput ::Input1 ) ) ;
assert! ( input . just_released . contains ( & DummyInput ::Input2 ) ) ;
input . reset_all ( ) ;
assert! ( input . pressed . is_empty ( ) ) ;
assert! ( input . just_pressed . is_empty ( ) ) ;
assert! ( input . just_released . is_empty ( ) ) ;
}
2020-12-01 06:58:49 +00:00
#[ test ]
2022-04-25 13:16:24 +00:00
fn test_clear ( ) {
2023-12-06 20:32:34 +00:00
let mut input = ButtonInput ::default ( ) ;
2020-12-01 06:58:49 +00:00
2022-04-25 13:16:24 +00:00
// Pressed
input . press ( DummyInput ::Input1 ) ;
assert! ( input . pressed ( DummyInput ::Input1 ) ) ;
assert! ( input . just_pressed ( DummyInput ::Input1 ) ) ;
assert! ( ! input . just_released ( DummyInput ::Input1 ) ) ;
input . clear ( ) ;
assert! ( input . pressed ( DummyInput ::Input1 ) ) ;
assert! ( ! input . just_pressed ( DummyInput ::Input1 ) ) ;
assert! ( ! input . just_released ( DummyInput ::Input1 ) ) ;
// Released
input . press ( DummyInput ::Input1 ) ;
input . release ( DummyInput ::Input1 ) ;
assert! ( ! input . pressed ( DummyInput ::Input1 ) ) ;
assert! ( ! input . just_pressed ( DummyInput ::Input1 ) ) ;
assert! ( input . just_released ( DummyInput ::Input1 ) ) ;
input . clear ( ) ;
assert! ( ! input . pressed ( DummyInput ::Input1 ) ) ;
assert! ( ! input . just_pressed ( DummyInput ::Input1 ) ) ;
assert! ( ! input . just_released ( DummyInput ::Input1 ) ) ;
}
#[ test ]
fn test_get_pressed ( ) {
2023-12-06 20:32:34 +00:00
let mut input = ButtonInput ::default ( ) ;
2022-04-25 13:16:24 +00:00
input . press ( DummyInput ::Input1 ) ;
input . press ( DummyInput ::Input2 ) ;
let pressed = input . get_pressed ( ) ;
assert_eq! ( pressed . len ( ) , 2 ) ;
for pressed_input in pressed {
assert! ( input . pressed . contains ( pressed_input ) ) ;
2020-12-01 06:58:49 +00:00
}
2022-04-25 13:16:24 +00:00
}
2020-12-01 06:58:49 +00:00
2022-04-25 13:16:24 +00:00
#[ test ]
fn test_get_just_pressed ( ) {
2023-12-06 20:32:34 +00:00
let mut input = ButtonInput ::default ( ) ;
2022-04-25 13:16:24 +00:00
input . press ( DummyInput ::Input1 ) ;
input . press ( DummyInput ::Input2 ) ;
let just_pressed = input . get_just_pressed ( ) ;
assert_eq! ( just_pressed . len ( ) , 2 ) ;
for just_pressed_input in just_pressed {
assert! ( input . just_pressed . contains ( just_pressed_input ) ) ;
}
}
#[ test ]
fn test_get_just_released ( ) {
2023-12-06 20:32:34 +00:00
let mut input = ButtonInput ::default ( ) ;
2022-04-25 13:16:24 +00:00
input . press ( DummyInput ::Input1 ) ;
input . press ( DummyInput ::Input2 ) ;
input . release ( DummyInput ::Input1 ) ;
input . release ( DummyInput ::Input2 ) ;
let just_released = input . get_just_released ( ) ;
assert_eq! ( just_released . len ( ) , 2 ) ;
for just_released_input in just_released {
assert! ( input . just_released . contains ( just_released_input ) ) ;
}
}
#[ test ]
fn test_general_input_handling ( ) {
2023-12-06 20:32:34 +00:00
let mut input = ButtonInput ::default ( ) ;
2020-12-01 06:58:49 +00:00
// Test pressing
input . press ( DummyInput ::Input1 ) ;
input . press ( DummyInput ::Input2 ) ;
2022-04-25 13:16:24 +00:00
// Check if they were `just_pressed` (pressed on this update)
2020-12-01 06:58:49 +00:00
assert! ( input . just_pressed ( DummyInput ::Input1 ) ) ;
assert! ( input . just_pressed ( DummyInput ::Input2 ) ) ;
// Check if they are also marked as pressed
assert! ( input . pressed ( DummyInput ::Input1 ) ) ;
assert! ( input . pressed ( DummyInput ::Input2 ) ) ;
2022-04-25 13:16:24 +00:00
// Clear the `input`, removing `just_pressed` and `just_released`
2021-04-13 03:13:48 +00:00
input . clear ( ) ;
2020-12-01 06:58:49 +00:00
2022-04-25 13:16:24 +00:00
// Check if they're marked `just_pressed`
2020-12-01 06:58:49 +00:00
assert! ( ! input . just_pressed ( DummyInput ::Input1 ) ) ;
assert! ( ! input . just_pressed ( DummyInput ::Input2 ) ) ;
// Check if they're marked as pressed
2022-04-04 22:10:00 +00:00
assert! ( input . pressed ( DummyInput ::Input1 ) ) ;
assert! ( input . pressed ( DummyInput ::Input2 ) ) ;
2020-12-01 06:58:49 +00:00
// Release the inputs and check state
input . release ( DummyInput ::Input1 ) ;
input . release ( DummyInput ::Input2 ) ;
2022-04-25 13:16:24 +00:00
// Check if they're marked as `just_released` (released on this update)
2020-12-01 06:58:49 +00:00
assert! ( input . just_released ( DummyInput ::Input1 ) ) ;
assert! ( input . just_released ( DummyInput ::Input2 ) ) ;
// Check that they're not incorrectly marked as pressed
assert! ( ! input . pressed ( DummyInput ::Input1 ) ) ;
assert! ( ! input . pressed ( DummyInput ::Input2 ) ) ;
2021-04-13 03:13:48 +00:00
// Clear the `Input` and check for removal from `just_released`
input . clear ( ) ;
2020-12-01 06:58:49 +00:00
// Check that they're not incorrectly marked as just released
assert! ( ! input . just_released ( DummyInput ::Input1 ) ) ;
assert! ( ! input . just_released ( DummyInput ::Input2 ) ) ;
2022-04-25 13:16:24 +00:00
// Set up an `Input` to test resetting
2023-12-06 20:32:34 +00:00
let mut input = ButtonInput ::default ( ) ;
2020-12-01 06:58:49 +00:00
input . press ( DummyInput ::Input1 ) ;
input . release ( DummyInput ::Input2 ) ;
2022-04-25 13:16:24 +00:00
// Reset the `Input` and test if it was reset correctly
2020-12-01 06:58:49 +00:00
input . reset ( DummyInput ::Input1 ) ;
input . reset ( DummyInput ::Input2 ) ;
assert! ( ! input . just_pressed ( DummyInput ::Input1 ) ) ;
assert! ( ! input . pressed ( DummyInput ::Input1 ) ) ;
assert! ( ! input . just_released ( DummyInput ::Input2 ) ) ;
}
}