4 use sdl2::HapticSubsystem;
5 use sdl2::JoystickSubsystem;
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;
12 use time::{Duration, prelude::*};
14 #[derive(Debug, Default)]
17 pub time_pressed: Duration,
18 pub time_released: Duration,
20 pub was_pressed: bool,
25 fn update(&mut self, device: &Joystick, dt: Duration) {
26 self.was_pressed = self.is_pressed;
27 self.is_pressed = match device.button(self.id as u32) {
29 if !self.was_pressed {
30 self.time_pressed = 0.seconds();
31 self.toggle = !self.toggle;
33 self.time_pressed += dt;
38 self.time_released = 0.seconds();
40 self.time_released += dt;
43 Err(_) => { panic!("invalid button {}", self.id) }
48 #[derive(Debug, Default)]
56 fn update(&mut self, device: &Joystick, _dt: Duration) {
57 self.val = match device.axis(self.id as u32) {
58 Ok(val) => val as f32 / 32768.0,
59 Err(_) => panic!("invalid axis {}", self.id),
64 #[derive(Debug, Default)]
75 fn update(&mut self, device: &Joystick, _dt: Duration) {
76 self.x = match device.axis(self.idx as u32) {
77 Ok(val) => val as f32 / 32768.0,
78 Err(_) => panic!("invalid x axis {}", self.idx),
80 self.y = match device.axis(self.idy as u32) {
81 Ok(val) => val as f32 / 32768.0,
82 Err(_) => panic!("invalid y axis {}", self.idy),
84 self.a = Radians(self.y.atan2(self.x) as f64);
86 let x = (self.x / self.y).abs().min(1.0);
87 let y = (self.y / self.x).abs().min(1.0);
88 (self.x.powi(2) + self.y.powi(2)).sqrt() / (x.powi(2) + y.powi(2)).sqrt()
92 #[inline(always)] #[allow(dead_code)] fn up(&self) -> bool { self.y > 0.99 }
93 #[inline(always)] #[allow(dead_code)] fn down(&self) -> bool { self.y < -0.99 }
94 #[inline(always)] #[allow(dead_code)] fn left(&self) -> bool { self.x < -0.99 }
95 #[inline(always)] #[allow(dead_code)] fn right(&self) -> bool { self.x > 0.99 }
97 pub fn to_point(&self) -> Point2D<f64> {
104 pub fn to_adjusted_point(&self) -> Point2D<f64> {
105 Point2D::from(self.a) * self.len as f64
109 impl From<&Stick> for Point2D<f64> {
110 fn from(item: &Stick) -> Self {
118 impl From<&Stick> for (f64, f64) {
119 fn from(item: &Stick) -> Self {
120 (item.x as f64, item.y as f64)
124 #[derive(Eq, PartialEq, Hash)]
125 enum DeviceControls {
151 #[derive(Eq, PartialEq, Hash)]
152 enum ActionControls {
163 pub struct Controller {
164 pub device: Joystick,
165 haptic: Option<Rc<RefCell<Haptic>>>,
175 pub fn new(device: Joystick, haptic: Option<Rc<RefCell<Haptic>>>) -> Self {
176 let action_map = get_action_mapping();
177 let device_map = get_device_mapping(&device.name());
178 let mut ctrl = Controller {
181 mov: Default::default(),
182 aim: Default::default(),
183 jump: Default::default(),
184 start: Default::default(),
185 shoot: Default::default(),
187 ctrl.set_mapping(&action_map, &device_map);
191 fn set_mapping(&mut self, action: &HashMap<ActionControls, DeviceControls>, device: &HashMap<DeviceControls, u8>) {
192 self.mov.idx = *action.get(&ActionControls::MovementX).map(|i| device.get(i)).flatten().unwrap();
193 self.mov.idy = *action.get(&ActionControls::MovementY).map(|i| device.get(i)).flatten().unwrap();
194 self.aim.idx = *action.get(&ActionControls::AimX).map(|i| device.get(i)).flatten().unwrap();
195 self.aim.idy = *action.get(&ActionControls::AimY).map(|i| device.get(i)).flatten().unwrap();
196 self.jump.id = *action.get(&ActionControls::Jump).map(|i| device.get(i)).flatten().unwrap();
197 self.shoot.id = *action.get(&ActionControls::Shoot).map(|i| device.get(i)).flatten().unwrap();
198 self.start.id = *action.get(&ActionControls::Start).map(|i| device.get(i)).flatten().unwrap();
201 pub fn update(&mut self, dt: Duration) {
202 self.mov.update(&self.device, dt);
203 self.aim.update(&self.device, dt);
204 self.jump.update(&self.device, dt);
205 self.shoot.update(&self.device, dt);
206 self.start.update(&self.device, dt);
210 pub fn rumble(&self, strength: f32, duration: Duration) {
211 if let Some(h) = &self.haptic {
212 h.borrow_mut().rumble_play(strength, duration.whole_milliseconds() as u32);
217 fn get_action_mapping() -> HashMap<ActionControls, DeviceControls> {
219 ActionControls::MovementX => DeviceControls::AxisLX,
220 ActionControls::MovementY => DeviceControls::AxisLY,
221 ActionControls::AimX => DeviceControls::AxisRX,
222 ActionControls::AimY => DeviceControls::AxisRY,
223 ActionControls::Jump => DeviceControls::ButtonL1,
224 ActionControls::Shoot => DeviceControls::ButtonR1,
225 ActionControls::Start => DeviceControls::ButtonStart
229 fn get_device_mapping(device_name: &str) -> HashMap<DeviceControls, u8> {
231 "Sony PLAYSTATION(R)3 Controller" => hashmap!(
232 DeviceControls::AxisLX => 0,
233 DeviceControls::AxisLY => 1,
234 DeviceControls::AxisRX => 3,
235 DeviceControls::AxisRY => 4,
236 DeviceControls::AxisL2 => 2,
237 DeviceControls::AxisR2 => 5,
238 DeviceControls::ButtonA => 0,
239 DeviceControls::ButtonB => 1,
240 DeviceControls::ButtonY => 3,
241 DeviceControls::ButtonX => 2,
242 DeviceControls::ButtonSelect => 8,
243 DeviceControls::ButtonStart => 9,
244 DeviceControls::ButtonHome => 10,
245 DeviceControls::ButtonL3 => 11,
246 DeviceControls::ButtonR3 => 12,
247 DeviceControls::ButtonL1 => 4,
248 DeviceControls::ButtonR1 => 5,
249 DeviceControls::ButtonL2 => 6,
250 DeviceControls::ButtonR2 => 7,
251 DeviceControls::ButtonUp => 13,
252 DeviceControls::ButtonDown => 14,
253 DeviceControls::ButtonLeft => 15,
254 DeviceControls::ButtonRight => 16
256 _ => panic!("No controller mapping for device '{}'", device_name)
261 pub struct ControllerManager {
262 pub joystick: JoystickSubsystem,
263 haptic: Rc<HapticSubsystem>,
264 pub controllers: HashMap<u32, Rc<RefCell<Controller>>>,
267 impl ControllerManager {
268 pub fn new(joystick: JoystickSubsystem, haptic: HapticSubsystem) -> Self {
269 joystick.set_event_state(true);
270 let mut c = ControllerManager {
272 haptic: Rc::new(haptic),
273 controllers: HashMap::new(),
280 for i in 0..self.joystick.num_joysticks().unwrap() {
285 pub fn update(&mut self, dt: Duration) {
286 self.controllers.iter().for_each(|(_, v)| v.borrow_mut().update(dt));
289 pub fn handle_event(&mut self, event: &Event) {
291 Event::JoyDeviceAdded { which, .. } => { self.add_device(*which) }
292 Event::JoyDeviceRemoved { which, .. } => { self.remove_device(*which) }
293 // Event::JoyButtonDown { which, button_idx, .. } => { println!("device {} button {} down!", which, button_idx) }
294 // Event::JoyButtonUp { which, button_idx, .. } => { println!("device {} button {} up!", which, button_idx) }
295 // Event::JoyAxisMotion { which, axis_idx, .. } => { println!("device {} axis motion {}!", which, axis_idx) }
300 fn add_device(&mut self, id: u32) {
301 println!("device added ({})!", id);
302 let mut device = self.joystick.open(id).unwrap();
303 println!("opened {}", device.name());
306 note about set_rumble (for dualshock 3 at least):
307 the active range for the low frequency is from 65536/4 to 65536 and escalates in large steps throughout the range
308 the active range for the high frequency is from 256 to 65536 and effect is the same throughout the whole range
310 let haptic = match device.set_rumble(0, 256, 100) {
311 Ok(_) => self.haptic.open_from_joystick_id(id).ok(),
315 if self.controllers.contains_key(&id) {
319 let detached = self.controllers.values().find(|c| !c.borrow().device.attached());
322 let mut c = c.borrow_mut();
324 c.haptic = haptic.map(|h| Rc::new(RefCell::new(h)));
327 let c = Rc::new(RefCell::new(Controller::new(device, haptic.map(|h| Rc::new(RefCell::new(h))))));
328 self.controllers.insert(id, c);
333 fn remove_device(&mut self, id: i32) {
334 println!("device removed ({})!", id);