@@ -11,7 +11,7 @@ use bevy::ecs::system::StaticSystemParam;
1111use bevy:: ecs:: system:: lifetimeless:: SRes ;
1212use bevy:: input:: mouse:: {
1313 AccumulatedMouseMotion , AccumulatedMouseScroll , MouseButton , MouseButtonInput , MouseMotion ,
14- MouseWheel ,
14+ MouseScrollUnit , MouseWheel ,
1515} ;
1616use bevy:: input:: { ButtonInput , ButtonState } ;
1717use bevy:: math:: FloatOrd ;
@@ -609,6 +609,7 @@ impl Hash for MouseScrollDirection {
609609/// ```rust
610610/// use bevy::prelude::*;
611611/// use bevy::input::InputPlugin;
612+ /// use bevy::input::mouse::MouseScrollUnit;
612613/// use leafwing_input_manager::plugin::CentralInputStorePlugin;
613614/// use leafwing_input_manager::prelude::*;
614615/// use leafwing_input_manager::user_input::testing_utils::FetchUserInput;
@@ -617,7 +618,12 @@ impl Hash for MouseScrollDirection {
617618/// app.add_plugins((InputPlugin, CentralInputStorePlugin));
618619///
619620/// // Y-axis movement
620- /// let input = MouseScrollAxis::Y;
621+ /// let mut input = MouseScrollAxis::Y;
622+ ///
623+ /// // You can configure which [`MouseScrollUnit`] this Axis uses.
624+ /// // The default is [`MouseScrollUnit::Pixel`]
625+ /// input.mouse_scroll_unit = MouseScrollUnit::Line;
626+ /// assert_eq!(input.mouse_scroll_unit, MouseScrollUnit::Line);
621627///
622628/// // Scrolling on the chosen axis activates the input
623629/// MouseScrollAxis::Y.set_value(app.world_mut(), 1.0);
@@ -634,6 +640,9 @@ pub struct MouseScrollAxis {
634640 /// The axis that this input tracks.
635641 pub axis : DualAxisType ,
636642
643+ /// The [`MouseScrollUnit`] this axis uses
644+ pub mouse_scroll_unit : MouseScrollUnit ,
645+
637646 /// A processing pipeline that handles input values.
638647 pub processors : Vec < AxisProcessor > ,
639648}
@@ -643,12 +652,14 @@ impl MouseScrollAxis {
643652 pub const X : Self = Self {
644653 axis : DualAxisType :: X ,
645654 processors : Vec :: new ( ) ,
655+ mouse_scroll_unit : MouseScrollUnit :: Pixel ,
646656 } ;
647657
648658 /// Vertical scrolling of the mouse wheel. No processing is applied to raw data from the mouse.
649659 pub const Y : Self = Self {
650660 axis : DualAxisType :: Y ,
651661 processors : Vec :: new ( ) ,
662+ mouse_scroll_unit : MouseScrollUnit :: Pixel ,
652663 } ;
653664}
654665
@@ -697,7 +708,7 @@ impl Axislike for MouseScrollAxis {
697708 /// The `window` field will be filled with a placeholder value.
698709 fn set_value ( & self , world : & mut World , value : f32 ) {
699710 let message = MouseWheel {
700- unit : bevy :: input :: mouse :: MouseScrollUnit :: Pixel ,
711+ unit : self . mouse_scroll_unit ,
701712 x : if self . axis == DualAxisType :: X {
702713 value
703714 } else {
@@ -747,14 +758,20 @@ impl WithAxisProcessingPipelineExt for MouseScrollAxis {
747758/// ```rust
748759/// use bevy::prelude::*;
749760/// use bevy::input::InputPlugin;
761+ /// use bevy::input::mouse::MouseScrollUnit;
750762/// use leafwing_input_manager::plugin::CentralInputStorePlugin;
751763/// use leafwing_input_manager::prelude::*;
752764/// use leafwing_input_manager::user_input::testing_utils::FetchUserInput;
753765///
754766/// let mut app = App::new();
755767/// app.add_plugins((InputPlugin, CentralInputStorePlugin));
756768///
757- /// let input = MouseScroll::default();
769+ /// let mut input = MouseScroll::default();
770+ ///
771+ /// // You can configure which [`MouseScrollUnit`] this Axis uses.
772+ /// // The default is [`MouseScrollUnit::Pixel`]
773+ /// input.mouse_scroll_unit = MouseScrollUnit::Line;
774+ /// assert_eq!(input.mouse_scroll_unit, MouseScrollUnit::Line);
758775///
759776/// // Scrolling on either axis activates the input
760777/// MouseScrollAxis::Y.set_value(app.world_mut(), 3.0);
@@ -765,13 +782,25 @@ impl WithAxisProcessingPipelineExt for MouseScrollAxis {
765782/// let doubled = MouseScroll::default().sensitivity_y(2.0);
766783/// assert_eq!(app.read_dual_axis_values(doubled), Vec2::new(0.0, 6.0));
767784/// ```
768- #[ derive( Debug , Default , Clone , PartialEq , Eq , Hash , Reflect , Serialize , Deserialize ) ]
785+ #[ derive( Debug , Clone , PartialEq , Eq , Hash , Reflect , Serialize , Deserialize ) ]
769786#[ must_use]
770787pub struct MouseScroll {
788+ /// The [`MouseScrollUnit`] this axis uses
789+ pub mouse_scroll_unit : MouseScrollUnit ,
790+
771791 /// A processing pipeline that handles input values.
772792 pub processors : Vec < DualAxisProcessor > ,
773793}
774794
795+ impl Default for MouseScroll {
796+ fn default ( ) -> Self {
797+ Self {
798+ mouse_scroll_unit : MouseScrollUnit :: Pixel ,
799+ processors : Vec :: new ( ) ,
800+ }
801+ }
802+ }
803+
775804impl UpdatableInput for MouseScroll {
776805 type SourceData = SRes < AccumulatedMouseScroll > ;
777806
@@ -822,7 +851,7 @@ impl DualAxislike for MouseScroll {
822851 world
823852 . resource_mut :: < Messages < MouseWheel > > ( )
824853 . write ( MouseWheel {
825- unit : bevy :: input :: mouse :: MouseScrollUnit :: Pixel ,
854+ unit : self . mouse_scroll_unit ,
826855 x : value. x ,
827856 y : value. y ,
828857 window : Entity :: PLACEHOLDER ,
@@ -919,6 +948,56 @@ mod tests {
919948 assert ! ( right. pressed( inputs, gamepad) ) ;
920949 }
921950
951+ #[ test]
952+ fn test_user_input_mouse_button_kind ( ) {
953+ let mouse_button = MouseButton :: Left ;
954+ assert_eq ! ( mouse_button. kind( ) , InputControlKind :: Button ) ;
955+ }
956+
957+ #[ test]
958+ fn test_mouse_button_set_value_press ( ) {
959+ let mut app = test_app ( ) ;
960+ let mouse_button = MouseButton :: Left ;
961+ mouse_button. set_value ( app. world_mut ( ) , 1.0 ) ;
962+
963+ let mut mouse_motion_messages = app
964+ . world_mut ( )
965+ . get_resource_mut :: < Messages < MouseButtonInput > > ( )
966+ . unwrap ( ) ;
967+
968+ assert_eq ! ( mouse_motion_messages. len( ) , 1 ) ;
969+ assert_eq ! (
970+ mouse_motion_messages. drain( ) . next( ) . unwrap( ) ,
971+ MouseButtonInput {
972+ button: MouseButton :: Left ,
973+ state: ButtonState :: Pressed ,
974+ window: Entity :: PLACEHOLDER ,
975+ }
976+ ) ;
977+ }
978+
979+ #[ test]
980+ fn test_mouse_button_set_value_release ( ) {
981+ let mut app = test_app ( ) ;
982+ let mouse_button = MouseButton :: Left ;
983+ mouse_button. set_value ( app. world_mut ( ) , 0.0 ) ;
984+
985+ let mut mouse_motion_messages = app
986+ . world_mut ( )
987+ . get_resource_mut :: < Messages < MouseButtonInput > > ( )
988+ . unwrap ( ) ;
989+
990+ assert_eq ! ( mouse_motion_messages. len( ) , 1 ) ;
991+ assert_eq ! (
992+ mouse_motion_messages. drain( ) . next( ) . unwrap( ) ,
993+ MouseButtonInput {
994+ button: MouseButton :: Left ,
995+ state: ButtonState :: Released ,
996+ window: Entity :: PLACEHOLDER ,
997+ }
998+ ) ;
999+ }
1000+
9221001 #[ test]
9231002 fn test_mouse_move ( ) {
9241003 let mouse_move_up = MouseMoveDirection :: UP ;
@@ -996,6 +1075,123 @@ mod tests {
9961075 assert_eq ! ( mouse_move. axis_pair( inputs, gamepad) , data) ;
9971076 }
9981077
1078+ #[ test]
1079+ fn test_mouse_move_direction_set_valid_threshold ( ) {
1080+ let mouse_move_direction = MouseMoveDirection :: UP . threshold ( 0.5 ) ;
1081+
1082+ assert_eq ! ( mouse_move_direction. threshold, 0.5 ) ;
1083+ }
1084+
1085+ #[ test]
1086+ #[ should_panic = "assertion failed: threshold >= 0.0" ]
1087+ fn test_mouse_move_direction_set_invalid_threshold ( ) {
1088+ let _ = MouseMoveDirection :: UP . threshold ( -0.5 ) ;
1089+ }
1090+
1091+ #[ test]
1092+ fn test_mouse_move_direction_kind ( ) {
1093+ let mouse_move_direction = MouseMoveDirection :: UP ;
1094+
1095+ assert_eq ! ( mouse_move_direction. kind( ) , InputControlKind :: Button ) ;
1096+ }
1097+
1098+ #[ test]
1099+ fn test_mouse_move_axis_processing_pipeline ( ) {
1100+ let mouse_move_axis = MouseMoveAxis :: X . with_processor ( AxisProcessor :: Inverted ) ;
1101+
1102+ assert_eq ! ( mouse_move_axis. processors. len( ) , 1 ) ;
1103+ assert_eq ! (
1104+ mouse_move_axis. processors. first( ) . unwrap( ) ,
1105+ & AxisProcessor :: Inverted
1106+ ) ;
1107+
1108+ let mouse_move_axis =
1109+ mouse_move_axis. replace_processing_pipeline ( vec ! [ AxisProcessor :: Digital ] ) ;
1110+
1111+ assert_eq ! ( mouse_move_axis. processors. len( ) , 1 ) ;
1112+ assert_eq ! (
1113+ mouse_move_axis. processors. first( ) . unwrap( ) ,
1114+ & AxisProcessor :: Digital
1115+ ) ;
1116+
1117+ let mouse_move_axis = mouse_move_axis. reset_processing_pipeline ( ) ;
1118+
1119+ assert_eq ! ( mouse_move_axis. processors. len( ) , 0 ) ;
1120+ }
1121+
1122+ #[ test]
1123+ fn test_mouse_move_processing_pipeline ( ) {
1124+ let mouse_move =
1125+ MouseMove :: default ( ) . with_processor ( DualAxisProcessor :: Inverted ( DualAxisInverted :: ALL ) ) ;
1126+
1127+ assert_eq ! ( mouse_move. processors. len( ) , 1 ) ;
1128+ assert_eq ! (
1129+ mouse_move. processors. first( ) . unwrap( ) ,
1130+ & DualAxisProcessor :: Inverted ( DualAxisInverted :: ALL ) ,
1131+ ) ;
1132+
1133+ let mouse_move = mouse_move. replace_processing_pipeline ( vec ! [ DualAxisProcessor :: Digital ] ) ;
1134+
1135+ assert_eq ! ( mouse_move. processors. len( ) , 1 ) ;
1136+ assert_eq ! (
1137+ mouse_move. processors. first( ) . unwrap( ) ,
1138+ & DualAxisProcessor :: Digital
1139+ ) ;
1140+
1141+ let mouse_move = mouse_move. reset_processing_pipeline ( ) ;
1142+
1143+ assert_eq ! ( mouse_move. processors. len( ) , 0 ) ;
1144+ }
1145+
1146+ #[ test]
1147+ fn test_mouse_scroll_processing_pipeline ( ) {
1148+ let mouse_scroll = MouseScroll :: default ( )
1149+ . with_processor ( DualAxisProcessor :: Inverted ( DualAxisInverted :: ALL ) ) ;
1150+
1151+ assert_eq ! ( mouse_scroll. processors. len( ) , 1 ) ;
1152+ assert_eq ! (
1153+ mouse_scroll. processors. first( ) . unwrap( ) ,
1154+ & DualAxisProcessor :: Inverted ( DualAxisInverted :: ALL ) ,
1155+ ) ;
1156+
1157+ let mouse_scroll =
1158+ mouse_scroll. replace_processing_pipeline ( vec ! [ DualAxisProcessor :: Digital ] ) ;
1159+
1160+ assert_eq ! ( mouse_scroll. processors. len( ) , 1 ) ;
1161+ assert_eq ! (
1162+ mouse_scroll. processors. first( ) . unwrap( ) ,
1163+ & DualAxisProcessor :: Digital
1164+ ) ;
1165+
1166+ let mouse_scroll = mouse_scroll. reset_processing_pipeline ( ) ;
1167+
1168+ assert_eq ! ( mouse_scroll. processors. len( ) , 0 ) ;
1169+ }
1170+
1171+ #[ test]
1172+ fn test_mouse_scroll_axis_processing_pipeline ( ) {
1173+ let mouse_scroll_axis = MouseScrollAxis :: X . with_processor ( AxisProcessor :: Inverted ) ;
1174+
1175+ assert_eq ! ( mouse_scroll_axis. processors. len( ) , 1 ) ;
1176+ assert_eq ! (
1177+ mouse_scroll_axis. processors. first( ) . unwrap( ) ,
1178+ & AxisProcessor :: Inverted ,
1179+ ) ;
1180+
1181+ let mouse_scroll_axis =
1182+ mouse_scroll_axis. replace_processing_pipeline ( vec ! [ AxisProcessor :: Digital ] ) ;
1183+
1184+ assert_eq ! ( mouse_scroll_axis. processors. len( ) , 1 ) ;
1185+ assert_eq ! (
1186+ mouse_scroll_axis. processors. first( ) . unwrap( ) ,
1187+ & AxisProcessor :: Digital
1188+ ) ;
1189+
1190+ let mouse_scroll_axis = mouse_scroll_axis. reset_processing_pipeline ( ) ;
1191+
1192+ assert_eq ! ( mouse_scroll_axis. processors. len( ) , 0 ) ;
1193+ }
1194+
9991195 #[ test]
10001196 fn test_mouse_scroll ( ) {
10011197 let mouse_scroll_up = MouseScrollDirection :: UP ;
@@ -1049,7 +1245,7 @@ mod tests {
10491245 assert_eq ! ( mouse_scroll_y. value( inputs, gamepad) , data. y) ;
10501246 assert_eq ! ( mouse_scroll. axis_pair( inputs, gamepad) , data) ;
10511247
1052- // Set changes in scrolling to (2.0, 3.0)
1248+ // Set changes in scrolling ` to (2.0, 3.0)
10531249 let data = Vec2 :: new ( 2.0 , 3.0 ) ;
10541250 let mut app = test_app ( ) ;
10551251 MouseScroll :: default ( ) . set_axis_pair ( app. world_mut ( ) , data) ;
@@ -1061,6 +1257,19 @@ mod tests {
10611257 assert_eq ! ( mouse_scroll. axis_pair( inputs, gamepad) , data) ;
10621258 }
10631259
1260+ #[ test]
1261+ fn test_mouse_scroll_direction_set_valid_threshold ( ) {
1262+ let mouse_scroll_direction = MouseScrollDirection :: UP . threshold ( 0.5 ) ;
1263+
1264+ assert_eq ! ( mouse_scroll_direction. threshold, 0.5 ) ;
1265+ }
1266+
1267+ #[ test]
1268+ #[ should_panic = "assertion failed: threshold >= 0.0" ]
1269+ fn test_mouse_scroll_direction_set_invalid_threshold ( ) {
1270+ let _ = MouseScrollDirection :: UP . threshold ( -0.5 ) ;
1271+ }
1272+
10641273 #[ test]
10651274 fn one_frame_accumulate_mouse_movement ( ) {
10661275 let mut app = test_app ( ) ;
0 commit comments