Replaced mapping struct with hashmap
[kaka/rust-sdl-test.git] / src / core / controller.rs
... / ...
CommitLineData
1use common::Point2D;
2use hashmap;
3use common::Radians;
4use sdl2::HapticSubsystem;
5use sdl2::JoystickSubsystem;
6use sdl2::event::Event;
7use sdl2::haptic::Haptic;
8use sdl2::joystick::Joystick;
9use std::cell::RefCell;
10use std::collections::HashMap;
11use std::rc::Rc;
12use time::{Duration, prelude::*};
13
14#[derive(Debug, Default)]
15pub 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
24impl 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)]
49pub struct Axis {
50 id: u8,
51 pub val: f32,
52}
53
54impl 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)]
65pub 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
74impl 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
109impl 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
118impl 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)]
125enum 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)]
152enum ActionControls {
153 MovementX,
154 MovementY,
155 AimX,
156 AimY,
157 Jump,
158 Shoot,
159 Start,
160}
161
162//#[derive(Debug)]
163pub 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
174impl 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
217fn 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
229fn 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)]
261pub struct ControllerManager {
262 pub joystick: JoystickSubsystem,
263 haptic: Rc<HapticSubsystem>,
264 pub controllers: HashMap<u32, Rc<RefCell<Controller>>>,
265}
266
267impl 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}