11use crate :: shared:: * ;
2- #[ cfg( not( target_os = "android" ) ) ]
32use gilrs:: ev:: state:: AxisData ;
4- #[ cfg( not( target_os = "android" ) ) ]
53use gilrs:: * ;
64
75/// A gilrs-powered gamepad input reader.
86///
97/// Shared between the hosted and the web device implementations.
108pub ( crate ) struct GamepadManager {
11- #[ cfg( not( target_os = "android" ) ) ]
129 gilrs : Gilrs ,
13- #[ cfg( not( target_os = "android" ) ) ]
1410 gamepad_id : Option < GamepadId > ,
1511 input : InputState ,
1612}
1713
1814impl GamepadManager {
1915 pub fn new ( ) -> Self {
20- #[ cfg( not( target_os = "android" ) ) ]
2116 let mut gilrs = Gilrs :: new ( ) . unwrap ( ) ;
22- #[ cfg( not( target_os = "android" ) ) ]
2317 let gamepad_id = gilrs. next_event ( ) . map ( |Event { id, .. } | id) ;
2418 Self {
25- #[ cfg( not( target_os = "android" ) ) ]
2619 gilrs,
27- #[ cfg( not( target_os = "android" ) ) ]
2820 gamepad_id,
2921 input : InputState :: default ( ) ,
3022 }
@@ -35,35 +27,27 @@ impl GamepadManager {
3527 }
3628
3729 pub fn read_input ( & mut self ) -> Option < InputState > {
38- #[ allow( unused_mut) ]
30+ // Detect gamepad
31+ if self . gamepad_id . is_none ( ) {
32+ self . gamepad_id = self . gilrs . next_event ( ) . map ( |Event { id, .. } | id) ;
33+ }
34+ // Consume all pending events to update the state
35+ while self . gilrs . next_event ( ) . is_some ( ) { }
36+ let Some ( gamepad_id) = self . gamepad_id else {
37+ return Some ( self . input . clone ( ) ) ;
38+ } ;
39+ let gamepad = self . gilrs . connected_gamepad ( gamepad_id) ?;
40+ let pad = read_pad ( gamepad) ;
41+ let buttons_array = [
42+ gamepad. is_pressed ( Button :: South ) , // A
43+ gamepad. is_pressed ( Button :: East ) , // B
44+ gamepad. is_pressed ( Button :: West ) , // X
45+ gamepad. is_pressed ( Button :: North ) , // Y
46+ gamepad. is_pressed ( Button :: Start ) ,
47+ ] ;
3948 let mut buttons = 0u8 ;
40- #[ allow( unused_mut, unused_assignments) ]
41- let mut pad = None ;
42-
43- #[ cfg( not( target_os = "android" ) ) ]
44- {
45- // Detect gamepad
46- if self . gamepad_id . is_none ( ) {
47- self . gamepad_id = self . gilrs . next_event ( ) . map ( |Event { id, .. } | id) ;
48- }
49- // Consume all pending events to update the state
50- while self . gilrs . next_event ( ) . is_some ( ) { }
51- let Some ( gamepad_id) = self . gamepad_id else {
52- return Some ( self . input . clone ( ) ) ;
53- } ;
54- let gamepad = self . gilrs . connected_gamepad ( gamepad_id) ?;
55- pad = read_pad ( gamepad) ;
56- let buttons_array = [
57- gamepad. is_pressed ( Button :: South ) , // A
58- gamepad. is_pressed ( Button :: East ) , // B
59- gamepad. is_pressed ( Button :: West ) , // X
60- gamepad. is_pressed ( Button :: North ) , // Y
61- gamepad. is_pressed ( Button :: Start ) ,
62- ] ;
63-
64- for b in buttons_array. into_iter ( ) . rev ( ) {
65- buttons = buttons << 1 | u8:: from ( b) ;
66- }
49+ for b in buttons_array. into_iter ( ) . rev ( ) {
50+ buttons = buttons << 1 | u8:: from ( b) ;
6751 }
6852
6953 // merge together input from gamepad and from keyboard
@@ -77,7 +61,6 @@ impl GamepadManager {
7761 }
7862}
7963
80- #[ cfg( not( target_os = "android" ) ) ]
8164/// Read state of sticks and convert it into touchpad state.
8265fn read_pad ( gamepad : Gamepad < ' _ > ) -> Option < Pad > {
8366 if gamepad. is_pressed ( Button :: DPadDown ) {
@@ -94,27 +77,13 @@ fn read_pad(gamepad: Gamepad<'_>) -> Option<Pad> {
9477 }
9578
9679 // Left stick works as pad only if it is pressed down.
97- //
98- // The only exceptions is Firefly Zero because
99- // it uses touchpad instead of stick and hence has no drift.
100- // Steam Controller, despite having two touchpads, by default uses
101- // stick for the left coordinate instead of the left touchpad.
102- //
103- // We don't check vendor ID for Firefly Zero because it's not settled yet.
104- // The dev version of the gamepad mode uses Flipper Devices Inc VID (0x37C1).
105- let is_precise = gamepad. product_id ( ) == Some ( 0x1337 ) ;
10680 let pad_pressed =
10781 gamepad. is_pressed ( Button :: LeftTrigger ) | gamepad. is_pressed ( Button :: LeftThumb ) ;
108- if is_precise || pad_pressed {
109- let maybe_point = make_point (
82+ if pad_pressed {
83+ return make_point (
11084 gamepad. axis_data ( Axis :: LeftStickX ) ,
11185 gamepad. axis_data ( Axis :: LeftStickY ) ,
11286 ) ;
113- let point = maybe_point?;
114- if is_precise && point. x == 0 && point. y == 0 {
115- return None ;
116- }
117- return Some ( point) ;
11887 } ;
11988
12089 let pad = make_point (
@@ -135,7 +104,6 @@ fn read_pad(gamepad: Gamepad<'_>) -> Option<Pad> {
135104 Some ( Pad { x, y } )
136105}
137106
138- #[ cfg( not( target_os = "android" ) ) ]
139107fn make_point ( x : Option < & AxisData > , y : Option < & AxisData > ) -> Option < Pad > {
140108 let x = data_to_i16 ( x) ;
141109 let y = data_to_i16 ( y) ;
@@ -145,7 +113,6 @@ fn make_point(x: Option<&AxisData>, y: Option<&AxisData>) -> Option<Pad> {
145113 }
146114}
147115
148- #[ cfg( not( target_os = "android" ) ) ]
149116fn data_to_i16 ( v : Option < & AxisData > ) -> Option < i16 > {
150117 let v = v?;
151118 let v = v. value ( ) ;
0 commit comments