3 use sdl2::HapticSubsystem;
4 use sdl2::JoystickSubsystem;
5 use sdl2::event::Event;
6 use sdl2::haptic::Haptic;
7 use sdl2::joystick::Joystick;
8 use std::cell::RefCell;
9 use std::collections::HashMap;
11 use time::{Duration, prelude::*};
13 #[derive(Debug, Default)]
16 pub time_pressed: Duration,
17 pub time_released: Duration,
19 pub was_pressed: bool,
24 fn update(&mut self, device: &Joystick, dt: Duration) {
25 self.was_pressed = self.is_pressed;
26 self.is_pressed = match device.button(self.id as u32) {
28 if !self.was_pressed {
29 self.time_pressed = 0.seconds();
30 self.toggle = !self.toggle;
32 self.time_pressed += dt;
37 self.time_released = 0.seconds();
39 self.time_released += dt;
42 Err(_) => { panic!("invalid button {}", self.id) }
47 #[derive(Debug, Default)]
55 fn update(&mut self, device: &Joystick, _dt: Duration) {
56 self.val = match device.axis(self.id as u32) {
57 Ok(val) => val as f32 / 32768.0,
58 Err(_) => panic!("invalid axis {}", self.id),
63 #[derive(Debug, Default)]
74 fn update(&mut self, device: &Joystick, _dt: Duration) {
75 self.x = match device.axis(self.idx as u32) {
76 Ok(val) => val as f32 / 32768.0,
77 Err(_) => panic!("invalid x axis {}", self.idx),
79 self.y = match device.axis(self.idy as u32) {
80 Ok(val) => val as f32 / 32768.0,
81 Err(_) => panic!("invalid y axis {}", self.idy),
83 self.a = Radians(self.y.atan2(self.x) as f64);
85 let x = (self.x / self.y).abs().min(1.0);
86 let y = (self.y / self.x).abs().min(1.0);
87 (self.x.powi(2) + self.y.powi(2)).sqrt() / (x.powi(2) + y.powi(2)).sqrt()
91 #[inline(always)] #[allow(dead_code)] fn up(&self) -> bool { self.y > 0.99 }
92 #[inline(always)] #[allow(dead_code)] fn down(&self) -> bool { self.y < -0.99 }
93 #[inline(always)] #[allow(dead_code)] fn left(&self) -> bool { self.x < -0.99 }
94 #[inline(always)] #[allow(dead_code)] fn right(&self) -> bool { self.x > 0.99 }
96 pub fn to_point(&self) -> Point2D<f64> {
103 pub fn to_adjusted_point(&self) -> Point2D<f64> {
104 Point2D::from(self.a) * self.len as f64
108 impl From<&Stick> for Point2D<f64> {
109 fn from(item: &Stick) -> Self {
117 impl From<&Stick> for (f64, f64) {
118 fn from(item: &Stick) -> Self {
119 (item.x as f64, item.y as f64)
159 pub struct Controller {
160 pub device: Joystick,
161 haptic: Option<Rc<RefCell<Haptic>>>,
171 pub fn new(device: Joystick, haptic: Option<Rc<RefCell<Haptic>>>) -> Self {
172 let mut ctrl = Controller {
175 mov: Default::default(),
176 aim: Default::default(),
177 jump: Default::default(),
178 start: Default::default(),
179 shoot: Default::default(),
181 let dualshock3 = Mapping {
209 ctrl.set_mapping(&dualshock3);
213 fn set_mapping(&mut self, map: &Mapping) {
214 self.mov.idx = map.axis.left_x;
215 self.mov.idy = map.axis.left_y;
216 self.aim.idx = map.axis.right_x;
217 self.aim.idy = map.axis.right_y;
218 self.jump.id = map.btn.left_shoulder;
219 self.shoot.id = map.btn.right_shoulder;
220 self.start.id = map.btn.start;
223 pub fn update(&mut self, dt: Duration) {
224 self.mov.update(&self.device, dt);
225 self.aim.update(&self.device, dt);
226 self.jump.update(&self.device, dt);
227 self.shoot.update(&self.device, dt);
228 self.start.update(&self.device, dt);
232 pub fn rumble(&self, strength: f32, duration: Duration) {
233 if let Some(h) = &self.haptic {
234 h.borrow_mut().rumble_play(strength, duration.whole_milliseconds() as u32);
240 pub struct ControllerManager {
241 pub joystick: JoystickSubsystem,
242 haptic: Rc<HapticSubsystem>,
243 pub controllers: HashMap<u32, Rc<RefCell<Controller>>>,
246 impl ControllerManager {
247 pub fn new(joystick: JoystickSubsystem, haptic: HapticSubsystem) -> Self {
248 joystick.set_event_state(true);
249 let mut c = ControllerManager {
251 haptic: Rc::new(haptic),
252 controllers: HashMap::new(),
259 for i in 0..self.joystick.num_joysticks().unwrap() {
264 pub fn update(&mut self, dt: Duration) {
265 self.controllers.iter().for_each(|(_, v)| v.borrow_mut().update(dt));
268 pub fn handle_event(&mut self, event: &Event) {
270 Event::JoyDeviceAdded { which, .. } => { self.add_device(*which) }
271 Event::JoyDeviceRemoved { which, .. } => { self.remove_device(*which) }
272 // Event::JoyButtonDown { which, button_idx, .. } => { println!("device {} button {} down!", which, button_idx) }
273 // Event::JoyButtonUp { which, button_idx, .. } => { println!("device {} button {} up!", which, button_idx) }
274 // Event::JoyAxisMotion { which, axis_idx, .. } => { println!("device {} axis motion {}!", which, axis_idx) }
279 fn add_device(&mut self, id: u32) {
280 println!("device added ({})!", id);
281 let mut device = self.joystick.open(id).unwrap();
282 println!("opened {}", device.name());
285 note about set_rumble (for dualshock 3 at least):
286 the active range for the low frequency is from 65536/4 to 65536 and escalates in large steps throughout the range
287 the active range for the high frequency is from 256 to 65536 and effect is the same throughout the whole range
289 let haptic = match device.set_rumble(0, 256, 100) {
290 Ok(_) => self.haptic.open_from_joystick_id(id).ok(),
294 if self.controllers.contains_key(&id) {
298 let detached = self.controllers.values().find(|c| !c.borrow().device.attached());
301 let mut c = c.borrow_mut();
303 c.haptic = haptic.map(|h| Rc::new(RefCell::new(h)));
306 let c = Rc::new(RefCell::new(Controller::new(device, haptic.map(|h| Rc::new(RefCell::new(h))))));
307 self.controllers.insert(id, c);
312 fn remove_device(&mut self, id: i32) {
313 println!("device removed ({})!", id);