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)]
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);
86 #[inline(always)] #[allow(dead_code)] pub fn up(&self) -> bool { self.y < -0.99 }
87 #[inline(always)] #[allow(dead_code)] pub fn down(&self) -> bool { self.y > 0.99 }
88 #[inline(always)] #[allow(dead_code)] pub fn left(&self) -> bool { self.x < -0.99 }
89 #[inline(always)] #[allow(dead_code)] pub fn right(&self) -> bool { self.x > 0.99 }
91 pub fn to_axis_point(&self) -> Point<f64> {
92 point!(self.x as f64, self.y as f64)
95 pub fn to_point(&self) -> Point<f64> {
96 let p = point!(self.x as f64, self.y as f64);
105 impl From<&Stick> for Point<f64> {
106 fn from(item: &Stick) -> Self {
114 impl From<&Stick> for (f64, f64) {
115 fn from(item: &Stick) -> Self {
116 (item.x as f64, item.y as f64)
120 #[derive(Eq, PartialEq, Hash)]
121 enum DeviceControls {
147 #[derive(Eq, PartialEq, Hash)]
148 enum ActionControls {
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 action_map = get_action_mapping();
173 let device_map = get_device_mapping(&device.name());
174 let mut ctrl = Controller {
177 mov: Default::default(),
178 aim: Default::default(),
179 jump: Default::default(),
180 start: Default::default(),
181 shoot: Default::default(),
183 ctrl.set_mapping(&action_map, &device_map);
187 fn set_mapping(&mut self, action: &HashMap<ActionControls, DeviceControls>, device: &HashMap<DeviceControls, u8>) {
188 self.mov.idx = *action.get(&ActionControls::MovementX).map(|i| device.get(i)).flatten().unwrap();
189 self.mov.idy = *action.get(&ActionControls::MovementY).map(|i| device.get(i)).flatten().unwrap();
190 self.aim.idx = *action.get(&ActionControls::AimX).map(|i| device.get(i)).flatten().unwrap();
191 self.aim.idy = *action.get(&ActionControls::AimY).map(|i| device.get(i)).flatten().unwrap();
192 self.jump.id = *action.get(&ActionControls::Jump).map(|i| device.get(i)).flatten().unwrap();
193 self.shoot.id = *action.get(&ActionControls::Shoot).map(|i| device.get(i)).flatten().unwrap();
194 self.start.id = *action.get(&ActionControls::Start).map(|i| device.get(i)).flatten().unwrap();
197 pub fn update(&mut self, dt: Duration) {
198 self.mov.update(&self.device, dt);
199 self.aim.update(&self.device, dt);
200 self.jump.update(&self.device, dt);
201 self.shoot.update(&self.device, dt);
202 self.start.update(&self.device, dt);
206 pub fn rumble(&self, strength: f32, duration: Duration) {
207 if let Some(h) = &self.haptic {
208 h.borrow_mut().rumble_play(strength, duration.whole_milliseconds() as u32);
213 fn get_action_mapping() -> HashMap<ActionControls, DeviceControls> {
215 ActionControls::MovementX => DeviceControls::AxisLX,
216 ActionControls::MovementY => DeviceControls::AxisLY,
217 ActionControls::AimX => DeviceControls::AxisRX,
218 ActionControls::AimY => DeviceControls::AxisRY,
219 ActionControls::Jump => DeviceControls::ButtonA,
220 ActionControls::Shoot => DeviceControls::ButtonR1,
221 ActionControls::Start => DeviceControls::ButtonStart
225 fn get_device_mapping(device_name: &str) -> HashMap<DeviceControls, u8> {
227 "Sony PLAYSTATION(R)3 Controller" => hashmap!(
228 DeviceControls::AxisLX => 0,
229 DeviceControls::AxisLY => 1,
230 DeviceControls::AxisRX => 3,
231 DeviceControls::AxisRY => 4,
232 DeviceControls::AxisL2 => 2,
233 DeviceControls::AxisR2 => 5,
234 DeviceControls::ButtonA => 0,
235 DeviceControls::ButtonB => 1,
236 DeviceControls::ButtonY => 3,
237 DeviceControls::ButtonX => 2,
238 DeviceControls::ButtonSelect => 8,
239 DeviceControls::ButtonStart => 9,
240 DeviceControls::ButtonHome => 10,
241 DeviceControls::ButtonL3 => 11,
242 DeviceControls::ButtonR3 => 12,
243 DeviceControls::ButtonL1 => 4,
244 DeviceControls::ButtonR1 => 5,
245 DeviceControls::ButtonL2 => 6,
246 DeviceControls::ButtonR2 => 7,
247 DeviceControls::ButtonUp => 13,
248 DeviceControls::ButtonDown => 14,
249 DeviceControls::ButtonLeft => 15,
250 DeviceControls::ButtonRight => 16
252 _ => panic!("No controller mapping for device '{}'", device_name)
257 pub struct ControllerManager {
258 pub joystick: JoystickSubsystem,
259 haptic: Rc<HapticSubsystem>,
260 pub controllers: HashMap<u32, Rc<RefCell<Controller>>>,
263 impl ControllerManager {
264 pub fn new(joystick: JoystickSubsystem, haptic: HapticSubsystem) -> Self {
265 joystick.set_event_state(true);
266 let mut c = ControllerManager {
268 haptic: Rc::new(haptic),
269 controllers: HashMap::new(),
276 for i in 0..self.joystick.num_joysticks().unwrap() {
281 pub fn update(&mut self, dt: Duration) {
282 self.controllers.iter().for_each(|(_, v)| v.borrow_mut().update(dt));
285 pub fn handle_event(&mut self, event: &Event) {
287 Event::JoyDeviceAdded { which, .. } => { self.add_device(*which) }
288 Event::JoyDeviceRemoved { which, .. } => { self.remove_device(*which) }
289 // Event::JoyButtonDown { which, button_idx, .. } => { println!("device {} button {} down!", which, button_idx) }
290 // Event::JoyButtonUp { which, button_idx, .. } => { println!("device {} button {} up!", which, button_idx) }
291 // Event::JoyAxisMotion { which, axis_idx, .. } => { println!("device {} axis motion {}!", which, axis_idx) }
296 fn add_device(&mut self, id: u32) {
297 println!("device added ({})!", id);
298 let mut device = self.joystick.open(id).unwrap();
299 println!("opened {}", device.name());
302 note about set_rumble (for dualshock 3 at least):
303 the active range for the low frequency is from 65536/4 to 65536 and escalates in large steps throughout the range
304 the active range for the high frequency is from 256 to 65536 and effect is the same throughout the whole range
306 let haptic = match device.set_rumble(0, 256, 100) {
307 Ok(_) => self.haptic.open_from_joystick_id(id).ok(),
311 if self.controllers.contains_key(&id) {
315 let detached = self.controllers.values().find(|c| !c.borrow().device.attached());
318 let mut c = c.borrow_mut();
320 c.haptic = haptic.map(|h| Rc::new(RefCell::new(h)));
323 let c = Rc::new(RefCell::new(Controller::new(device, haptic.map(|h| Rc::new(RefCell::new(h))))));
324 self.controllers.insert(id, c);
329 fn remove_device(&mut self, id: i32) {
330 println!("device removed ({})!", id);