832480d6830686956003345f53c0fd0d63f0fa66
[kaka/rust-sdl-test.git] / src / core / controller.rs
1 use common::Point2D;
2 use hashmap;
3 use common::Radians;
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;
11 use std::rc::Rc;
12 use time::{Duration, prelude::*};
13
14 #[derive(Debug, Default)]
15 pub struct Button {
16     id: u8,
17     pub time_pressed: Duration,
18     pub time_released: Duration,
19     pub is_pressed: bool,
20     pub was_pressed: bool,
21     pub toggle: bool,
22 }
23
24 impl Button {
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) {
28             Ok(true) => {
29                 if !self.was_pressed {
30                     self.time_pressed = 0.seconds();
31                     self.toggle = !self.toggle;
32                 }
33                 self.time_pressed += dt;
34                 true
35             }
36             Ok(false) => {
37                 if self.was_pressed {
38                     self.time_released = 0.seconds();
39                 }
40                 self.time_released += dt;
41                 false
42             }
43             Err(_) => { panic!("invalid button {}", self.id) }
44         }
45     }
46 }
47
48 #[derive(Debug, Default)]
49 pub struct Axis {
50     id: u8,
51     pub val: f32,
52 }
53
54 impl Axis {
55     #[allow(dead_code)]
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),
60         }
61     }
62 }
63
64 #[derive(Debug, Default)]
65 pub struct Stick {
66     idx: u8,
67     idy: u8,
68     pub x: f32,
69     pub y: f32,
70     pub a: Radians,
71     pub len: f32,
72 }
73
74 impl Stick {
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),
79         };
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),
83         };
84         self.a = Radians(self.y.atan2(self.x) as f64);
85         self.len = {
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()
89         }
90     }
91
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 }
96
97     pub fn to_point(&self) -> Point2D<f64> {
98         Point2D {
99             x: self.x as f64,
100             y: self.y as f64,
101         }
102     }
103
104     pub fn to_adjusted_point(&self) -> Point2D<f64> {
105         Point2D::from(self.a) * self.len as f64
106     }
107 }
108
109 impl From<&Stick> for Point2D<f64> {
110     fn from(item: &Stick) -> Self {
111         Self {
112             x: item.x as f64,
113             y: item.y as f64,
114         }
115     }
116 }
117
118 impl From<&Stick> for (f64, f64) {
119     fn from(item: &Stick) -> Self {
120         (item.x as f64, item.y as f64)
121     }
122 }
123
124 #[derive(Eq, PartialEq, Hash)]
125 enum DeviceControls {
126     AxisLX,
127     AxisLY,
128     AxisRX,
129     AxisRY,
130     AxisL2,
131     AxisR2,
132     ButtonA,
133     ButtonB,
134     ButtonY,
135     ButtonX,
136     ButtonSelect,
137     ButtonStart,
138     ButtonHome,
139     ButtonL3,
140     ButtonR3,
141     ButtonL1,
142     ButtonR1,
143     ButtonL2,
144     ButtonR2,
145     ButtonUp,
146     ButtonDown,
147     ButtonLeft,
148     ButtonRight,
149 }
150
151 #[derive(Eq, PartialEq, Hash)]
152 enum ActionControls {
153     MovementX,
154     MovementY,
155     AimX,
156     AimY,
157     Jump,
158     Shoot,
159     Start,
160 }
161
162 //#[derive(Debug)]
163 pub struct Controller {
164     pub device: Joystick,
165     haptic: Option<Rc<RefCell<Haptic>>>,
166
167     pub mov: Stick,
168     pub aim: Stick,
169     pub jump: Button,
170     pub start: Button,
171     pub shoot: Button,
172 }
173
174 impl Controller {
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 {
179             device,
180             haptic,
181             mov: Default::default(),
182             aim: Default::default(),
183             jump: Default::default(),
184             start: Default::default(),
185             shoot: Default::default(),
186         };
187         ctrl.set_mapping(&action_map, &device_map);
188         ctrl
189     }
190
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();
199     }
200
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);
207     }
208
209     /// strength [0 - 1]
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);
213         }
214     }
215 }
216
217 fn get_action_mapping() -> HashMap<ActionControls, DeviceControls> {
218     hashmap!(
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
226     )
227 }
228
229 fn get_device_mapping(device_name: &str) -> HashMap<DeviceControls, u8> {
230     match device_name {
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
255         ),
256         _ => panic!("No controller mapping for device '{}'", device_name)
257     }
258 }
259
260 //#[derive(Debug)]
261 pub struct ControllerManager {
262     pub joystick: JoystickSubsystem,
263     haptic: Rc<HapticSubsystem>,
264     pub controllers: HashMap<u32, Rc<RefCell<Controller>>>,
265 }
266
267 impl ControllerManager {
268     pub fn new(joystick: JoystickSubsystem, haptic: HapticSubsystem) -> Self {
269         joystick.set_event_state(true);
270         let mut c = ControllerManager {
271             joystick,
272             haptic: Rc::new(haptic),
273             controllers: HashMap::new(),
274         };
275         c.init();
276         c
277     }
278
279     fn init(&mut self) {
280         for i in 0..self.joystick.num_joysticks().unwrap() {
281             self.add_device(i);
282         }
283     }
284
285     pub fn update(&mut self, dt: Duration) {
286         self.controllers.iter().for_each(|(_, v)| v.borrow_mut().update(dt));
287     }
288
289     pub fn handle_event(&mut self, event: &Event) {
290         match 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) }
296             _ => {}
297         }
298     }
299
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());
304
305         /*
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
309          */
310         let haptic = match device.set_rumble(0, 256, 100) {
311             Ok(_) => self.haptic.open_from_joystick_id(id).ok(),
312             Err(_) => None
313         };
314
315         if self.controllers.contains_key(&id) {
316             return;
317         }
318
319         let detached = self.controllers.values().find(|c| !c.borrow().device.attached());
320         match detached {
321             Some(c) => {
322                 let mut c = c.borrow_mut();
323                 c.device = device;
324                 c.haptic = haptic.map(|h| Rc::new(RefCell::new(h)));
325             }
326             None => {
327                 let c = Rc::new(RefCell::new(Controller::new(device, haptic.map(|h| Rc::new(RefCell::new(h))))));
328                 self.controllers.insert(id, c);
329             }
330         };
331     }
332
333     fn remove_device(&mut self, id: i32) {
334         println!("device removed ({})!", id);
335         // TODO
336     }
337 }