Point2D -> Point
[kaka/rust-sdl-test.git] / src / core / controller.rs
... / ...
CommitLineData
1use common::Point;
2use {hashmap, point};
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}
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 }
85
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 }
90
91 pub fn to_axis_point(&self) -> Point<f64> {
92 point!(self.x as f64, self.y as f64)
93 }
94
95 pub fn to_point(&self) -> Point<f64> {
96 let p = point!(self.x as f64, self.y as f64);
97 if p.length() > 1.0 {
98 p.normalized()
99 } else {
100 p
101 }
102 }
103}
104
105impl From<&Stick> for Point<f64> {
106 fn from(item: &Stick) -> Self {
107 Self {
108 x: item.x as f64,
109 y: item.y as f64,
110 }
111 }
112}
113
114impl From<&Stick> for (f64, f64) {
115 fn from(item: &Stick) -> Self {
116 (item.x as f64, item.y as f64)
117 }
118}
119
120#[derive(Eq, PartialEq, Hash)]
121enum DeviceControls {
122 AxisLX,
123 AxisLY,
124 AxisRX,
125 AxisRY,
126 AxisL2,
127 AxisR2,
128 ButtonA,
129 ButtonB,
130 ButtonY,
131 ButtonX,
132 ButtonSelect,
133 ButtonStart,
134 ButtonHome,
135 ButtonL3,
136 ButtonR3,
137 ButtonL1,
138 ButtonR1,
139 ButtonL2,
140 ButtonR2,
141 ButtonUp,
142 ButtonDown,
143 ButtonLeft,
144 ButtonRight,
145}
146
147#[derive(Eq, PartialEq, Hash)]
148enum ActionControls {
149 MovementX,
150 MovementY,
151 AimX,
152 AimY,
153 Jump,
154 Shoot,
155 Start,
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 action_map = get_action_mapping();
173 let device_map = get_device_mapping(&device.name());
174 let mut ctrl = Controller {
175 device,
176 haptic,
177 mov: Default::default(),
178 aim: Default::default(),
179 jump: Default::default(),
180 start: Default::default(),
181 shoot: Default::default(),
182 };
183 ctrl.set_mapping(&action_map, &device_map);
184 ctrl
185 }
186
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();
195 }
196
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);
203 }
204
205 /// strength [0 - 1]
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);
209 }
210 }
211}
212
213fn get_action_mapping() -> HashMap<ActionControls, DeviceControls> {
214 hashmap!(
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
222 )
223}
224
225fn get_device_mapping(device_name: &str) -> HashMap<DeviceControls, u8> {
226 match device_name {
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
251 ),
252 _ => panic!("No controller mapping for device '{}'", device_name)
253 }
254}
255
256//#[derive(Debug)]
257pub struct ControllerManager {
258 pub joystick: JoystickSubsystem,
259 haptic: Rc<HapticSubsystem>,
260 pub controllers: HashMap<u32, Rc<RefCell<Controller>>>,
261}
262
263impl ControllerManager {
264 pub fn new(joystick: JoystickSubsystem, haptic: HapticSubsystem) -> Self {
265 joystick.set_event_state(true);
266 let mut c = ControllerManager {
267 joystick,
268 haptic: Rc::new(haptic),
269 controllers: HashMap::new(),
270 };
271 c.init();
272 c
273 }
274
275 fn init(&mut self) {
276 for i in 0..self.joystick.num_joysticks().unwrap() {
277 self.add_device(i);
278 }
279 }
280
281 pub fn update(&mut self, dt: Duration) {
282 self.controllers.iter().for_each(|(_, v)| v.borrow_mut().update(dt));
283 }
284
285 pub fn handle_event(&mut self, event: &Event) {
286 match 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) }
292 _ => {}
293 }
294 }
295
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());
300
301 /*
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
305 */
306 let haptic = match device.set_rumble(0, 256, 100) {
307 Ok(_) => self.haptic.open_from_joystick_id(id).ok(),
308 Err(_) => None
309 };
310
311 if self.controllers.contains_key(&id) {
312 return;
313 }
314
315 let detached = self.controllers.values().find(|c| !c.borrow().device.attached());
316 match detached {
317 Some(c) => {
318 let mut c = c.borrow_mut();
319 c.device = device;
320 c.haptic = haptic.map(|h| Rc::new(RefCell::new(h)));
321 }
322 None => {
323 let c = Rc::new(RefCell::new(Controller::new(device, haptic.map(|h| Rc::new(RefCell::new(h))))));
324 self.controllers.insert(id, c);
325 }
326 };
327 }
328
329 fn remove_device(&mut self, id: i32) {
330 println!("device removed ({})!", id);
331 // TODO
332 }
333}