diff --git a/crates/bevy_input/src/axis.rs b/crates/bevy_input/src/axis.rs index 529237c3f4..842527b015 100644 --- a/crates/bevy_input/src/axis.rs +++ b/crates/bevy_input/src/axis.rs @@ -1,6 +1,10 @@ use bevy_utils::HashMap; use std::hash::Hash; +/// Stores the position data of input devices of type T +/// +/// Values are stored as `f32` values, which range from `min` to `max`. +/// The valid range is from -1.0 to 1.0, inclusive. #[derive(Debug)] pub struct Axis { axis_data: HashMap, @@ -21,15 +25,82 @@ impl Axis where T: Copy + Eq + Hash, { - pub fn set(&mut self, axis: T, value: f32) -> Option { - self.axis_data.insert(axis, value) + pub const MIN: f32 = -1.0; + pub const MAX: f32 = 1.0; + + /// Inserts a position data for an input device, + /// restricting the position data to an interval `min..=max`. + /// + /// If the input device wasn't present before, [None] is returned. + /// + /// If the input device was present, the position data is updated, and the old value is returned. + pub fn set(&mut self, input_device: T, position_data: f32) -> Option { + let new_position_data = position_data.clamp(Self::MIN, Self::MAX); + self.axis_data.insert(input_device, new_position_data) } - pub fn get(&self, axis: T) -> Option { - self.axis_data.get(&axis).copied() + /// Returns a position data corresponding to the input device. + pub fn get(&self, input_device: T) -> Option { + self.axis_data.get(&input_device).copied() } - pub fn remove(&mut self, axis: T) -> Option { - self.axis_data.remove(&axis) + /// Removes the position data of the input device, + /// returning the position data if the input device was previously set. + pub fn remove(&mut self, input_device: T) -> Option { + self.axis_data.remove(&input_device) + } +} + +#[cfg(test)] +mod tests { + use crate::{ + gamepad::{Gamepad, GamepadButton, GamepadButtonType}, + Axis, + }; + + #[test] + fn test_axis_set() { + let cases = [ + (-1.5, Some(-1.0)), + (-1.1, Some(-1.0)), + (-1.0, Some(-1.0)), + (-0.9, Some(-0.9)), + (-0.1, Some(-0.1)), + (0.0, Some(0.0)), + (0.1, Some(0.1)), + (0.9, Some(0.9)), + (1.0, Some(1.0)), + (1.1, Some(1.0)), + (1.6, Some(1.0)), + ]; + + for (value, expected) in cases { + let gamepad_button = GamepadButton(Gamepad(1), GamepadButtonType::RightTrigger); + let mut axis = Axis::::default(); + + axis.set(gamepad_button, value); + + let actual = axis.get(gamepad_button); + assert_eq!(expected, actual); + } + } + + #[test] + fn test_axis_remove() { + let cases = [-1.0, -0.9, -0.1, 0.0, 0.1, 0.9, 1.0]; + + for value in cases { + let gamepad_button = GamepadButton(Gamepad(1), GamepadButtonType::RightTrigger); + let mut axis = Axis::::default(); + + axis.set(gamepad_button, value); + assert!(axis.get(gamepad_button).is_some()); + + axis.remove(gamepad_button); + let actual = axis.get(gamepad_button); + let expected = None; + + assert_eq!(expected, actual); + } } }