1 use common::{Angle, Point};
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)]
73 fn update(&mut self, device: &Joystick, _dt: Duration) {
74 self.x = match device.axis(self.idx as u32) {
75 Ok(val) => val as f32 / 32768.0,
76 Err(_) => panic!("invalid x axis {}", self.idx),
78 self.y = match device.axis(self.idy as u32) {
79 Ok(val) => val as f32 / 32768.0,
80 Err(_) => panic!("invalid y axis {}", self.idy),
82 self.a = point!(self.x as f64, self.y as f64).to_angle();
85 #[inline(always)] #[allow(dead_code)] pub fn up(&self) -> bool { self.y < -0.99 }
86 #[inline(always)] #[allow(dead_code)] pub fn down(&self) -> bool { self.y > 0.99 }
87 #[inline(always)] #[allow(dead_code)] pub fn left(&self) -> bool { self.x < -0.99 }
88 #[inline(always)] #[allow(dead_code)] pub fn right(&self) -> bool { self.x > 0.99 }
90 pub fn to_axis_point(&self) -> Point<f64> {
91 point!(self.x as f64, self.y as f64)
94 pub fn to_point(&self) -> Point<f64> {
95 let p = point!(self.x as f64, self.y as f64);
104 impl From<&Stick> for Point<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)
119 #[derive(Eq, PartialEq, Hash)]
120 enum DeviceControls {
145 use self::DeviceControls::*;
147 #[derive(Eq, PartialEq, Hash)]
148 enum ActionControls {
157 use self::ActionControls::*;
160 pub struct Controller {
161 pub device: Joystick,
162 haptic: Option<Rc<RefCell<Haptic>>>,
172 pub fn new(device: Joystick, haptic: Option<Rc<RefCell<Haptic>>>) -> Self {
173 let action_map = get_action_mapping();
174 let device_map = get_device_mapping(&device.name());
175 let mut ctrl = Controller {
178 mov: Default::default(),
179 aim: Default::default(),
180 jump: Default::default(),
181 start: Default::default(),
182 shoot: Default::default(),
184 ctrl.set_mapping(&action_map, &device_map);
188 fn set_mapping(&mut self, action: &HashMap<ActionControls, DeviceControls>, device: &HashMap<DeviceControls, u8>) {
189 self.mov.idx = *action.get(&MovementX).map(|i| device.get(i)).flatten().unwrap();
190 self.mov.idy = *action.get(&MovementY).map(|i| device.get(i)).flatten().unwrap();
191 self.aim.idx = *action.get(&AimX).map(|i| device.get(i)).flatten().unwrap();
192 self.aim.idy = *action.get(&AimY).map(|i| device.get(i)).flatten().unwrap();
193 self.jump.id = *action.get(&Jump).map(|i| device.get(i)).flatten().unwrap();
194 self.shoot.id = *action.get(&Shoot).map(|i| device.get(i)).flatten().unwrap();
195 self.start.id = *action.get(&Start).map(|i| device.get(i)).flatten().unwrap();
198 pub fn update(&mut self, dt: Duration) {
199 self.mov.update(&self.device, dt);
200 self.aim.update(&self.device, dt);
201 self.jump.update(&self.device, dt);
202 self.shoot.update(&self.device, dt);
203 self.start.update(&self.device, dt);
207 pub fn rumble(&self, strength: f32, duration: Duration) {
208 if let Some(h) = &self.haptic {
209 h.borrow_mut().rumble_play(strength, duration.whole_milliseconds() as u32);
214 fn get_action_mapping() -> HashMap<ActionControls, DeviceControls> {
226 fn get_device_mapping(device_name: &str) -> HashMap<DeviceControls, u8> {
228 "Sony PLAYSTATION(R)3 Controller" => hashmap!(
253 _ => panic!("No controller mapping for device '{}'", device_name)
258 pub struct ControllerManager {
259 pub joystick: JoystickSubsystem,
260 haptic: Rc<HapticSubsystem>,
261 pub controllers: HashMap<u32, Rc<RefCell<Controller>>>,
264 impl ControllerManager {
265 pub fn new(joystick: JoystickSubsystem, haptic: HapticSubsystem) -> Self {
266 joystick.set_event_state(true);
267 let mut c = ControllerManager {
269 haptic: Rc::new(haptic),
270 controllers: HashMap::new(),
277 for i in 0..self.joystick.num_joysticks().unwrap() {
282 pub fn update(&mut self, dt: Duration) {
283 self.controllers.iter().for_each(|(_, v)| v.borrow_mut().update(dt));
286 pub fn handle_event(&mut self, event: &Event) {
288 Event::JoyDeviceAdded { which, .. } => { self.add_device(*which) }
289 Event::JoyDeviceRemoved { which, .. } => { self.remove_device(*which) }
290 // Event::JoyButtonDown { which, button_idx, .. } => { println!("device {} button {} down!", which, button_idx) }
291 // Event::JoyButtonUp { which, button_idx, .. } => { println!("device {} button {} up!", which, button_idx) }
292 // Event::JoyAxisMotion { which, axis_idx, .. } => { println!("device {} axis motion {}!", which, axis_idx) }
297 fn add_device(&mut self, id: u32) {
298 println!("device added ({})!", id);
299 let mut device = self.joystick.open(id).unwrap();
300 println!("opened {}", device.name());
303 note about set_rumble (for dualshock 3 at least):
304 the active range for the low frequency is from 65536/4 to 65536 and escalates in large steps throughout the range
305 the active range for the high frequency is from 256 to 65536 and effect is the same throughout the whole range
307 let haptic = match device.set_rumble(0, 256, 100) {
308 Ok(_) => self.haptic.open_from_joystick_id(id).ok(),
312 if self.controllers.contains_key(&id) {
316 let detached = self.controllers.values().find(|c| !c.borrow().device.attached());
319 let mut c = c.borrow_mut();
321 c.haptic = haptic.map(|h| Rc::new(RefCell::new(h)));
324 let c = Rc::new(RefCell::new(Controller::new(device, haptic.map(|h| Rc::new(RefCell::new(h))))));
325 self.controllers.insert(id, c);
330 fn remove_device(&mut self, id: i32) {
331 println!("device removed ({})!", id);