127c3096d470b4f852831d94d9e6e4f07299cc00
[kaka/rust-sdl-test.git] / src / core / controller.rs
1 use sdl2::JoystickSubsystem;
2 use common::Nanoseconds;
3 use common::Radians;
4 use common::Point2D;
5 use sdl2::HapticSubsystem;
6 use sdl2::event::Event;
7 use sdl2::haptic::Haptic;
8 use sdl2::joystick::Joystick;
9 use std::cell::RefCell;
10 use std::collections::HashMap;
11 use std::rc::Rc;
12
13 #[derive(Debug, Default)]
14 pub struct Button {
15     pub time_pressed: Nanoseconds,
16     pub time_released: Nanoseconds,
17     pub is_pressed: bool,
18     pub was_pressed: bool,
19     pub toggle: bool,
20 }
21
22 impl Button {
23     fn update(&mut self, device: &Joystick, dt: Nanoseconds, btn: u8) {
24         self.was_pressed = self.is_pressed;
25         self.is_pressed = match device.button(btn as u32) {
26             Ok(true) => {
27                 if !self.was_pressed {
28                     self.time_pressed = 0;
29                     self.toggle = !self.toggle;
30                 }
31                 self.time_pressed += dt;
32                 true
33             }
34             Ok(false) => {
35                 if self.was_pressed {
36                     self.time_released = 0;
37                 }
38                 self.time_released += dt;
39                 false
40             }
41             Err(_) => { panic!("invalid button {}", btn) }
42         }
43     }
44 }
45
46 #[derive(Debug, Default)]
47 pub struct Axis {
48     pub val: f32,
49 }
50
51 impl Axis {
52     #[allow(dead_code)]
53     fn update(&mut self, device: &Joystick, _dt: Nanoseconds, axis: u8) {
54         self.val = match device.axis(axis as u32) {
55             Ok(val) => val as f32 / 32768.0,
56             Err(_) => panic!("invalid axis {}", axis),
57         }
58     }
59 }
60
61 #[derive(Debug, Default)]
62 pub struct Stick {
63     pub x: f32,
64     pub y: f32,
65     pub a: Radians,
66     pub len: f32,
67 }
68
69 impl Stick {
70     fn update(&mut self, device: &Joystick, _dt: Nanoseconds, x_axis: u8, y_axis: u8) {
71         self.x = match device.axis(x_axis as u32) {
72             Ok(val) => val as f32 / 32768.0,
73             Err(_) => panic!("invalid x axis {}", x_axis),
74         };
75         self.y = match device.axis(y_axis as u32) {
76             Ok(val) => val as f32 / 32768.0,
77             Err(_) => panic!("invalid y axis {}", y_axis),
78         };
79         self.a = Radians(self.y.atan2(self.x) as f64);
80         self.len = {
81             let x = (self.x / self.y).abs().min(1.0);
82             let y = (self.y / self.x).abs().min(1.0);
83             (self.x.powi(2) + self.y.powi(2)).sqrt() / (x.powi(2) + y.powi(2)).sqrt()
84         }
85     }
86
87     #[inline(always)] #[allow(dead_code)] fn up(&self) -> bool { self.y > 0.99 }
88     #[inline(always)] #[allow(dead_code)] fn down(&self) -> bool { self.y < -0.99 }
89     #[inline(always)] #[allow(dead_code)] fn left(&self) -> bool { self.x < -0.99 }
90     #[inline(always)] #[allow(dead_code)] fn right(&self) -> bool { self.x > 0.99 }
91
92     pub fn to_point(&self) -> Point2D<f64> {
93         Point2D {
94             x: self.x as f64,
95             y: self.y as f64,
96         }
97     }
98
99     pub fn to_adjusted_point(&self) -> Point2D<f64> {
100         Point2D::from(self.a) * self.len as f64
101     }
102 }
103
104 impl From<&Stick> for Point2D<f64> {
105     fn from(item: &Stick) -> Self {
106         Self {
107             x: item.x as f64,
108             y: item.y as f64,
109         }
110     }
111 }
112
113 impl From<&Stick> for (f64, f64) {
114     fn from(item: &Stick) -> Self {
115         (item.x as f64, item.y as f64)
116     }
117 }
118
119 //#[derive(Debug)]
120 pub struct Controller {
121     pub device: Joystick,
122     haptic: Option<Rc<RefCell<Haptic>>>,
123
124     pub mov: Stick,
125     pub aim: Stick,
126     pub jump: Button,
127     pub start: Button,
128     pub shoot: Button,
129 }
130
131 impl Controller {
132     pub fn new(device: Joystick, haptic: Option<Rc<RefCell<Haptic>>>) -> Self {
133         Controller {
134             device,
135             haptic,
136             mov: Default::default(),
137             aim: Default::default(),
138             jump: Default::default(),
139             start: Default::default(),
140             shoot: Default::default(),
141         }
142     }
143
144     pub fn update(&mut self, dt: Nanoseconds) {
145         self.mov.update(&self.device, dt, 0, 1); // left stick
146         self.aim.update(&self.device, dt, 3, 4); // right stick
147         self.jump.update(&self.device, dt, 4);   // left shoulder
148         self.shoot.update(&self.device, dt, 5); // right shoulder
149         self.start.update(&self.device, dt, 9);  // start
150     }
151
152     /// strength [0 - 1]
153     pub fn rumble(&self, strength: f32, duration_ms: u32) {
154         if let Some(h) = &self.haptic {
155             h.borrow_mut().rumble_play(strength, duration_ms);
156         }
157     }
158 }
159
160 //#[derive(Debug)]
161 pub struct ControllerManager {
162     pub joystick: JoystickSubsystem,
163     haptic: Rc<HapticSubsystem>,
164     pub controllers: HashMap<u32, Rc<RefCell<Controller>>>,
165 }
166
167 impl ControllerManager {
168     pub fn new(joystick: JoystickSubsystem, haptic: HapticSubsystem) -> Self {
169         joystick.set_event_state(true);
170         let mut c = ControllerManager {
171             joystick,
172             haptic: Rc::new(haptic),
173             controllers: HashMap::new(),
174         };
175         c.init();
176         c
177     }
178
179     fn init(&mut self) {
180         for i in 0..self.joystick.num_joysticks().unwrap() {
181             self.add_device(i);
182         }
183     }
184
185     pub fn update(&mut self, dt: Nanoseconds) {
186         self.controllers.iter().for_each(|(_, v)| v.borrow_mut().update(dt));
187     }
188
189     pub fn handle_event(&mut self, event: &Event) {
190         match event {
191             Event::JoyDeviceAdded { which, .. } => { self.add_device(*which) }
192             Event::JoyDeviceRemoved { which, .. } => { self.remove_device(*which) }
193             Event::JoyButtonDown { which, button_idx, .. } => { println!("device {} button {} down!", which, button_idx) }
194             Event::JoyButtonUp { which, button_idx, .. } => { println!("device {} button {} up!", which, button_idx) }
195             Event::JoyAxisMotion { which, axis_idx, .. } => { println!("device {} axis motion {}!", which, axis_idx) }
196             _ => {}
197         }
198     }
199
200     fn add_device(&mut self, id: u32) {
201         println!("device added ({})!", id);
202         let mut device = self.joystick.open(id).unwrap();
203         println!("opened {}", device.name());
204
205         /*
206         note about set_rumble (for dualshock 3 at least):
207         the active range for the low frequency is from 65536/4 to 65536 and escalates in large steps throughout the range
208         the active range for the high frequency is from 256 to 65536 and effect is the same throughout the whole range
209          */
210         let haptic = match device.set_rumble(0, 256, 100) {
211             Ok(_) => self.haptic.open_from_joystick_id(id).ok(),
212             Err(_) => None
213         };
214
215         if self.controllers.contains_key(&id) {
216             return;
217         }
218
219         let detached = self.controllers.values().find(|c| !c.borrow().device.attached());
220         match detached {
221             Some(c) => {
222                 let mut c = c.borrow_mut();
223                 c.device = device;
224                 c.haptic = haptic.map(|h| Rc::new(RefCell::new(h)));
225             }
226             None => {
227                 let c = Rc::new(RefCell::new(Controller::new(device, haptic.map(|h| Rc::new(RefCell::new(h))))));
228                 self.controllers.insert(id, c);
229             }
230         };
231     }
232
233     fn remove_device(&mut self, id: i32) {
234         println!("device removed ({})!", id);
235         // TODO
236     }
237 }