Placeholder controller mapping
[kaka/rust-sdl-test.git] / src / core / controller.rs
CommitLineData
bf7b5671 1use common::Point2D;
902b2b31 2use common::Radians;
3f344b63 3use sdl2::HapticSubsystem;
902b2b31 4use sdl2::JoystickSubsystem;
3f344b63 5use sdl2::event::Event;
bf7b5671
TW
6use sdl2::haptic::Haptic;
7use sdl2::joystick::Joystick;
8use std::cell::RefCell;
9use std::collections::HashMap;
3f344b63 10use std::rc::Rc;
902b2b31 11use time::{Duration, prelude::*};
3f344b63 12
bf7b5671
TW
13#[derive(Debug, Default)]
14pub struct Button {
5d731022 15 id: u8,
902b2b31
TW
16 pub time_pressed: Duration,
17 pub time_released: Duration,
bf7b5671
TW
18 pub is_pressed: bool,
19 pub was_pressed: bool,
20 pub toggle: bool,
21}
22
23impl Button {
5d731022 24 fn update(&mut self, device: &Joystick, dt: Duration) {
bf7b5671 25 self.was_pressed = self.is_pressed;
5d731022 26 self.is_pressed = match device.button(self.id as u32) {
bf7b5671
TW
27 Ok(true) => {
28 if !self.was_pressed {
902b2b31 29 self.time_pressed = 0.seconds();
bf7b5671
TW
30 self.toggle = !self.toggle;
31 }
32 self.time_pressed += dt;
33 true
34 }
35 Ok(false) => {
36 if self.was_pressed {
902b2b31 37 self.time_released = 0.seconds();
bf7b5671
TW
38 }
39 self.time_released += dt;
40 false
41 }
5d731022 42 Err(_) => { panic!("invalid button {}", self.id) }
bf7b5671
TW
43 }
44 }
45}
46
47#[derive(Debug, Default)]
48pub struct Axis {
5d731022 49 id: u8,
bf7b5671
TW
50 pub val: f32,
51}
52
53impl Axis {
54 #[allow(dead_code)]
5d731022
TW
55 fn update(&mut self, device: &Joystick, _dt: Duration) {
56 self.val = match device.axis(self.id as u32) {
bf7b5671 57 Ok(val) => val as f32 / 32768.0,
5d731022 58 Err(_) => panic!("invalid axis {}", self.id),
bf7b5671
TW
59 }
60 }
61}
62
63#[derive(Debug, Default)]
64pub struct Stick {
5d731022
TW
65 idx: u8,
66 idy: u8,
bf7b5671
TW
67 pub x: f32,
68 pub y: f32,
69 pub a: Radians,
70 pub len: f32,
71}
72
73impl Stick {
5d731022
TW
74 fn update(&mut self, device: &Joystick, _dt: Duration) {
75 self.x = match device.axis(self.idx as u32) {
bf7b5671 76 Ok(val) => val as f32 / 32768.0,
5d731022 77 Err(_) => panic!("invalid x axis {}", self.idx),
bf7b5671 78 };
5d731022 79 self.y = match device.axis(self.idy as u32) {
bf7b5671 80 Ok(val) => val as f32 / 32768.0,
5d731022 81 Err(_) => panic!("invalid y axis {}", self.idy),
bf7b5671
TW
82 };
83 self.a = Radians(self.y.atan2(self.x) as f64);
84 self.len = {
85 let x = (self.x / self.y).abs().min(1.0);
86 let y = (self.y / self.x).abs().min(1.0);
87 (self.x.powi(2) + self.y.powi(2)).sqrt() / (x.powi(2) + y.powi(2)).sqrt()
88 }
89 }
90
91 #[inline(always)] #[allow(dead_code)] fn up(&self) -> bool { self.y > 0.99 }
92 #[inline(always)] #[allow(dead_code)] fn down(&self) -> bool { self.y < -0.99 }
93 #[inline(always)] #[allow(dead_code)] fn left(&self) -> bool { self.x < -0.99 }
94 #[inline(always)] #[allow(dead_code)] fn right(&self) -> bool { self.x > 0.99 }
95
96 pub fn to_point(&self) -> Point2D<f64> {
97 Point2D {
98 x: self.x as f64,
99 y: self.y as f64,
100 }
101 }
102
103 pub fn to_adjusted_point(&self) -> Point2D<f64> {
104 Point2D::from(self.a) * self.len as f64
105 }
106}
107
108impl From<&Stick> for Point2D<f64> {
109 fn from(item: &Stick) -> Self {
110 Self {
111 x: item.x as f64,
112 y: item.y as f64,
113 }
114 }
115}
116
117impl From<&Stick> for (f64, f64) {
118 fn from(item: &Stick) -> Self {
119 (item.x as f64, item.y as f64)
120 }
3f344b63
TW
121}
122
5d731022
TW
123#[allow(dead_code)]
124struct Axes {
125 left_x: u8,
126 left_y: u8,
127 right_x: u8,
128 right_y: u8,
129 trigger_left: u8,
130 trigger_right: u8,
131}
132
133#[allow(dead_code)]
134struct Buttons {
135 a: u8,
136 b: u8,
137 x: u8,
138 y: u8,
139 select: u8,
140 start: u8,
141 left_stick: u8,
142 right_stick: u8,
143 left_shoulder: u8,
144 right_shoulder: u8,
145 left_trigger: u8,
146 right_trigger: u8,
147 d_pad_up: u8,
148 d_pad_down: u8,
149 d_pad_left: u8,
150 d_pad_right: u8,
151}
152
153struct Mapping {
154 axis: Axes,
155 btn: Buttons,
156}
157
3f344b63
TW
158//#[derive(Debug)]
159pub struct Controller {
bf7b5671 160 pub device: Joystick,
3f344b63 161 haptic: Option<Rc<RefCell<Haptic>>>,
bf7b5671
TW
162
163 pub mov: Stick,
164 pub aim: Stick,
165 pub jump: Button,
166 pub start: Button,
167 pub shoot: Button,
168}
169
170impl Controller {
171 pub fn new(device: Joystick, haptic: Option<Rc<RefCell<Haptic>>>) -> Self {
5d731022 172 let mut ctrl = Controller {
bf7b5671
TW
173 device,
174 haptic,
175 mov: Default::default(),
176 aim: Default::default(),
177 jump: Default::default(),
178 start: Default::default(),
179 shoot: Default::default(),
5d731022
TW
180 };
181 let dualshock3 = Mapping {
182 axis: Axes {
183 left_x: 0,
184 left_y: 1,
185 right_x: 3,
186 right_y: 4,
187 trigger_left: 2,
188 trigger_right: 5,
189 },
190 btn: Buttons {
191 a: 0,
192 b: 1,
193 x: 3,
194 y: 2,
195 select: 8,
196 start: 9,
197 left_stick: 11,
198 right_stick: 12,
199 left_shoulder: 4,
200 right_shoulder: 5,
201 left_trigger: 6,
202 right_trigger: 7,
203 d_pad_up: 13,
204 d_pad_down: 14,
205 d_pad_left: 15,
206 d_pad_right: 16,
207 },
208 };
209 ctrl.set_mapping(&dualshock3);
210 ctrl
211 }
212
213 fn set_mapping(&mut self, map: &Mapping) {
214 self.mov.idx = map.axis.left_x;
215 self.mov.idy = map.axis.left_y;
216 self.aim.idx = map.axis.right_x;
217 self.aim.idy = map.axis.right_y;
218 self.jump.id = map.btn.left_shoulder;
219 self.shoot.id = map.btn.right_shoulder;
220 self.start.id = map.btn.start;
bf7b5671
TW
221 }
222
902b2b31 223 pub fn update(&mut self, dt: Duration) {
5d731022
TW
224 self.mov.update(&self.device, dt);
225 self.aim.update(&self.device, dt);
226 self.jump.update(&self.device, dt);
227 self.shoot.update(&self.device, dt);
228 self.start.update(&self.device, dt);
bf7b5671
TW
229 }
230
231 /// strength [0 - 1]
902b2b31 232 pub fn rumble(&self, strength: f32, duration: Duration) {
bf7b5671 233 if let Some(h) = &self.haptic {
902b2b31 234 h.borrow_mut().rumble_play(strength, duration.whole_milliseconds() as u32);
bf7b5671
TW
235 }
236 }
237}
238
239//#[derive(Debug)]
240pub struct ControllerManager {
241 pub joystick: JoystickSubsystem,
242 haptic: Rc<HapticSubsystem>,
243 pub controllers: HashMap<u32, Rc<RefCell<Controller>>>,
3f344b63
TW
244}
245
246impl ControllerManager {
bf7b5671
TW
247 pub fn new(joystick: JoystickSubsystem, haptic: HapticSubsystem) -> Self {
248 joystick.set_event_state(true);
b0566120 249 let mut c = ControllerManager {
bf7b5671 250 joystick,
3f344b63 251 haptic: Rc::new(haptic),
b0566120
TW
252 controllers: HashMap::new(),
253 };
254 c.init();
255 c
256 }
257
258 fn init(&mut self) {
bf7b5671 259 for i in 0..self.joystick.num_joysticks().unwrap() {
b0566120 260 self.add_device(i);
3f344b63
TW
261 }
262 }
263
902b2b31 264 pub fn update(&mut self, dt: Duration) {
bf7b5671
TW
265 self.controllers.iter().for_each(|(_, v)| v.borrow_mut().update(dt));
266 }
267
3f344b63
TW
268 pub fn handle_event(&mut self, event: &Event) {
269 match event {
bf7b5671
TW
270 Event::JoyDeviceAdded { which, .. } => { self.add_device(*which) }
271 Event::JoyDeviceRemoved { which, .. } => { self.remove_device(*which) }
5d731022
TW
272 // Event::JoyButtonDown { which, button_idx, .. } => { println!("device {} button {} down!", which, button_idx) }
273 // Event::JoyButtonUp { which, button_idx, .. } => { println!("device {} button {} up!", which, button_idx) }
274 // Event::JoyAxisMotion { which, axis_idx, .. } => { println!("device {} axis motion {}!", which, axis_idx) }
3f344b63
TW
275 _ => {}
276 }
277 }
278
bf7b5671 279 fn add_device(&mut self, id: u32) {
3f344b63 280 println!("device added ({})!", id);
bf7b5671
TW
281 let mut device = self.joystick.open(id).unwrap();
282 println!("opened {}", device.name());
ca99d4d7
TW
283
284 /*
285 note about set_rumble (for dualshock 3 at least):
286 the active range for the low frequency is from 65536/4 to 65536 and escalates in large steps throughout the range
287 the active range for the high frequency is from 256 to 65536 and effect is the same throughout the whole range
288 */
bf7b5671 289 let haptic = match device.set_rumble(0, 256, 100) {
3f344b63
TW
290 Ok(_) => self.haptic.open_from_joystick_id(id).ok(),
291 Err(_) => None
292 };
293
b0566120
TW
294 if self.controllers.contains_key(&id) {
295 return;
296 }
297
bf7b5671 298 let detached = self.controllers.values().find(|c| !c.borrow().device.attached());
ca99d4d7
TW
299 match detached {
300 Some(c) => {
301 let mut c = c.borrow_mut();
bf7b5671 302 c.device = device;
ca99d4d7
TW
303 c.haptic = haptic.map(|h| Rc::new(RefCell::new(h)));
304 }
305 None => {
bf7b5671 306 let c = Rc::new(RefCell::new(Controller::new(device, haptic.map(|h| Rc::new(RefCell::new(h))))));
b0566120 307 self.controllers.insert(id, c);
ca99d4d7
TW
308 }
309 };
3f344b63
TW
310 }
311
bf7b5671 312 fn remove_device(&mut self, id: i32) {
3f344b63 313 println!("device removed ({})!", id);
ca99d4d7 314 // TODO
3f344b63
TW
315 }
316}