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)]
15 pub time_pressed: Duration,
16 pub time_released: Duration,
18 pub was_pressed: bool,
23 fn update(&mut self, device: &Joystick, dt: Duration, btn: u8) {
24 self.was_pressed = self.is_pressed;
25 self.is_pressed = match device.button(btn as u32) {
27 if !self.was_pressed {
28 self.time_pressed = 0.seconds();
29 self.toggle = !self.toggle;
31 self.time_pressed += dt;
36 self.time_released = 0.seconds();
38 self.time_released += dt;
41 Err(_) => { panic!("invalid button {}", btn) }
46 #[derive(Debug, Default)]
53 fn update(&mut self, device: &Joystick, _dt: Duration, 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),
61 #[derive(Debug, Default)]
70 fn update(&mut self, device: &Joystick, _dt: Duration, 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),
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),
79 self.a = Radians(self.y.atan2(self.x) as f64);
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()
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 }
92 pub fn to_point(&self) -> Point2D<f64> {
99 pub fn to_adjusted_point(&self) -> Point2D<f64> {
100 Point2D::from(self.a) * self.len as f64
104 impl From<&Stick> for Point2D<f64> {
105 fn from(item: &Stick) -> Self {
113 impl From<&Stick> for (f64, f64) {
114 fn from(item: &Stick) -> Self {
115 (item.x as f64, item.y as f64)
120 pub struct Controller {
121 pub device: Joystick,
122 haptic: Option<Rc<RefCell<Haptic>>>,
132 pub fn new(device: Joystick, haptic: Option<Rc<RefCell<Haptic>>>) -> Self {
136 mov: Default::default(),
137 aim: Default::default(),
138 jump: Default::default(),
139 start: Default::default(),
140 shoot: Default::default(),
144 pub fn update(&mut self, dt: Duration) {
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
153 pub fn rumble(&self, strength: f32, duration: Duration) {
154 if let Some(h) = &self.haptic {
155 h.borrow_mut().rumble_play(strength, duration.whole_milliseconds() as u32);
161 pub struct ControllerManager {
162 pub joystick: JoystickSubsystem,
163 haptic: Rc<HapticSubsystem>,
164 pub controllers: HashMap<u32, Rc<RefCell<Controller>>>,
167 impl ControllerManager {
168 pub fn new(joystick: JoystickSubsystem, haptic: HapticSubsystem) -> Self {
169 joystick.set_event_state(true);
170 let mut c = ControllerManager {
172 haptic: Rc::new(haptic),
173 controllers: HashMap::new(),
180 for i in 0..self.joystick.num_joysticks().unwrap() {
185 pub fn update(&mut self, dt: Duration) {
186 self.controllers.iter().for_each(|(_, v)| v.borrow_mut().update(dt));
189 pub fn handle_event(&mut self, event: &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) }
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());
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
210 let haptic = match device.set_rumble(0, 256, 100) {
211 Ok(_) => self.haptic.open_from_joystick_id(id).ok(),
215 if self.controllers.contains_key(&id) {
219 let detached = self.controllers.values().find(|c| !c.borrow().device.attached());
222 let mut c = c.borrow_mut();
224 c.haptic = haptic.map(|h| Rc::new(RefCell::new(h)));
227 let c = Rc::new(RefCell::new(Controller::new(device, haptic.map(|h| Rc::new(RefCell::new(h))))));
228 self.controllers.insert(id, c);
233 fn remove_device(&mut self, id: i32) {
234 println!("device removed ({})!", id);