Placeholder controller mapping
[kaka/rust-sdl-test.git] / src / core / controller.rs
... / ...
CommitLineData
1use common::Point2D;
2use common::Radians;
3use sdl2::HapticSubsystem;
4use sdl2::JoystickSubsystem;
5use sdl2::event::Event;
6use sdl2::haptic::Haptic;
7use sdl2::joystick::Joystick;
8use std::cell::RefCell;
9use std::collections::HashMap;
10use std::rc::Rc;
11use time::{Duration, prelude::*};
12
13#[derive(Debug, Default)]
14pub struct Button {
15 id: u8,
16 pub time_pressed: Duration,
17 pub time_released: Duration,
18 pub is_pressed: bool,
19 pub was_pressed: bool,
20 pub toggle: bool,
21}
22
23impl Button {
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) {
27 Ok(true) => {
28 if !self.was_pressed {
29 self.time_pressed = 0.seconds();
30 self.toggle = !self.toggle;
31 }
32 self.time_pressed += dt;
33 true
34 }
35 Ok(false) => {
36 if self.was_pressed {
37 self.time_released = 0.seconds();
38 }
39 self.time_released += dt;
40 false
41 }
42 Err(_) => { panic!("invalid button {}", self.id) }
43 }
44 }
45}
46
47#[derive(Debug, Default)]
48pub struct Axis {
49 id: u8,
50 pub val: f32,
51}
52
53impl Axis {
54 #[allow(dead_code)]
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),
59 }
60 }
61}
62
63#[derive(Debug, Default)]
64pub struct Stick {
65 idx: u8,
66 idy: u8,
67 pub x: f32,
68 pub y: f32,
69 pub a: Radians,
70 pub len: f32,
71}
72
73impl Stick {
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),
78 };
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),
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 }
121}
122
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
158//#[derive(Debug)]
159pub struct Controller {
160 pub device: Joystick,
161 haptic: Option<Rc<RefCell<Haptic>>>,
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 {
172 let mut ctrl = Controller {
173 device,
174 haptic,
175 mov: Default::default(),
176 aim: Default::default(),
177 jump: Default::default(),
178 start: Default::default(),
179 shoot: Default::default(),
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;
221 }
222
223 pub fn update(&mut self, dt: Duration) {
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);
229 }
230
231 /// strength [0 - 1]
232 pub fn rumble(&self, strength: f32, duration: Duration) {
233 if let Some(h) = &self.haptic {
234 h.borrow_mut().rumble_play(strength, duration.whole_milliseconds() as u32);
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>>>,
244}
245
246impl ControllerManager {
247 pub fn new(joystick: JoystickSubsystem, haptic: HapticSubsystem) -> Self {
248 joystick.set_event_state(true);
249 let mut c = ControllerManager {
250 joystick,
251 haptic: Rc::new(haptic),
252 controllers: HashMap::new(),
253 };
254 c.init();
255 c
256 }
257
258 fn init(&mut self) {
259 for i in 0..self.joystick.num_joysticks().unwrap() {
260 self.add_device(i);
261 }
262 }
263
264 pub fn update(&mut self, dt: Duration) {
265 self.controllers.iter().for_each(|(_, v)| v.borrow_mut().update(dt));
266 }
267
268 pub fn handle_event(&mut self, event: &Event) {
269 match event {
270 Event::JoyDeviceAdded { which, .. } => { self.add_device(*which) }
271 Event::JoyDeviceRemoved { which, .. } => { self.remove_device(*which) }
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) }
275 _ => {}
276 }
277 }
278
279 fn add_device(&mut self, id: u32) {
280 println!("device added ({})!", id);
281 let mut device = self.joystick.open(id).unwrap();
282 println!("opened {}", device.name());
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 */
289 let haptic = match device.set_rumble(0, 256, 100) {
290 Ok(_) => self.haptic.open_from_joystick_id(id).ok(),
291 Err(_) => None
292 };
293
294 if self.controllers.contains_key(&id) {
295 return;
296 }
297
298 let detached = self.controllers.values().find(|c| !c.borrow().device.attached());
299 match detached {
300 Some(c) => {
301 let mut c = c.borrow_mut();
302 c.device = device;
303 c.haptic = haptic.map(|h| Rc::new(RefCell::new(h)));
304 }
305 None => {
306 let c = Rc::new(RefCell::new(Controller::new(device, haptic.map(|h| Rc::new(RefCell::new(h))))));
307 self.controllers.insert(id, c);
308 }
309 };
310 }
311
312 fn remove_device(&mut self, id: i32) {
313 println!("device removed ({})!", id);
314 // TODO
315 }
316}