Use durations everywhere!
[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 {
902b2b31
TW
15 pub time_pressed: Duration,
16 pub time_released: Duration,
bf7b5671
TW
17 pub is_pressed: bool,
18 pub was_pressed: bool,
19 pub toggle: bool,
20}
21
22impl Button {
902b2b31 23 fn update(&mut self, device: &Joystick, dt: Duration, btn: u8) {
bf7b5671
TW
24 self.was_pressed = self.is_pressed;
25 self.is_pressed = match device.button(btn as u32) {
26 Ok(true) => {
27 if !self.was_pressed {
902b2b31 28 self.time_pressed = 0.seconds();
bf7b5671
TW
29 self.toggle = !self.toggle;
30 }
31 self.time_pressed += dt;
32 true
33 }
34 Ok(false) => {
35 if self.was_pressed {
902b2b31 36 self.time_released = 0.seconds();
bf7b5671
TW
37 }
38 self.time_released += dt;
39 false
40 }
41 Err(_) => { panic!("invalid button {}", btn) }
42 }
43 }
44}
45
46#[derive(Debug, Default)]
47pub struct Axis {
48 pub val: f32,
49}
50
51impl Axis {
52 #[allow(dead_code)]
902b2b31 53 fn update(&mut self, device: &Joystick, _dt: Duration, axis: u8) {
bf7b5671
TW
54 self.val = match device.axis(axis as u32) {
55 Ok(val) => val as f32 / 32768.0,
56 Err(_) => panic!("invalid axis {}", axis),
57 }
58 }
59}
60
61#[derive(Debug, Default)]
62pub struct Stick {
63 pub x: f32,
64 pub y: f32,
65 pub a: Radians,
66 pub len: f32,
67}
68
69impl Stick {
902b2b31 70 fn update(&mut self, device: &Joystick, _dt: Duration, x_axis: u8, y_axis: u8) {
bf7b5671
TW
71 self.x = match device.axis(x_axis as u32) {
72 Ok(val) => val as f32 / 32768.0,
73 Err(_) => panic!("invalid x axis {}", x_axis),
74 };
75 self.y = match device.axis(y_axis as u32) {
76 Ok(val) => val as f32 / 32768.0,
77 Err(_) => panic!("invalid y axis {}", y_axis),
78 };
79 self.a = Radians(self.y.atan2(self.x) as f64);
80 self.len = {
81 let x = (self.x / self.y).abs().min(1.0);
82 let y = (self.y / self.x).abs().min(1.0);
83 (self.x.powi(2) + self.y.powi(2)).sqrt() / (x.powi(2) + y.powi(2)).sqrt()
84 }
85 }
86
87 #[inline(always)] #[allow(dead_code)] fn up(&self) -> bool { self.y > 0.99 }
88 #[inline(always)] #[allow(dead_code)] fn down(&self) -> bool { self.y < -0.99 }
89 #[inline(always)] #[allow(dead_code)] fn left(&self) -> bool { self.x < -0.99 }
90 #[inline(always)] #[allow(dead_code)] fn right(&self) -> bool { self.x > 0.99 }
91
92 pub fn to_point(&self) -> Point2D<f64> {
93 Point2D {
94 x: self.x as f64,
95 y: self.y as f64,
96 }
97 }
98
99 pub fn to_adjusted_point(&self) -> Point2D<f64> {
100 Point2D::from(self.a) * self.len as f64
101 }
102}
103
104impl From<&Stick> for Point2D<f64> {
105 fn from(item: &Stick) -> Self {
106 Self {
107 x: item.x as f64,
108 y: item.y as f64,
109 }
110 }
111}
112
113impl From<&Stick> for (f64, f64) {
114 fn from(item: &Stick) -> Self {
115 (item.x as f64, item.y as f64)
116 }
3f344b63
TW
117}
118
119//#[derive(Debug)]
120pub struct Controller {
bf7b5671 121 pub device: Joystick,
3f344b63 122 haptic: Option<Rc<RefCell<Haptic>>>,
bf7b5671
TW
123
124 pub mov: Stick,
125 pub aim: Stick,
126 pub jump: Button,
127 pub start: Button,
128 pub shoot: Button,
129}
130
131impl Controller {
132 pub fn new(device: Joystick, haptic: Option<Rc<RefCell<Haptic>>>) -> Self {
133 Controller {
134 device,
135 haptic,
136 mov: Default::default(),
137 aim: Default::default(),
138 jump: Default::default(),
139 start: Default::default(),
140 shoot: Default::default(),
141 }
142 }
143
902b2b31 144 pub fn update(&mut self, dt: Duration) {
bf7b5671
TW
145 self.mov.update(&self.device, dt, 0, 1); // left stick
146 self.aim.update(&self.device, dt, 3, 4); // right stick
147 self.jump.update(&self.device, dt, 4); // left shoulder
148 self.shoot.update(&self.device, dt, 5); // right shoulder
149 self.start.update(&self.device, dt, 9); // start
150 }
151
152 /// strength [0 - 1]
902b2b31 153 pub fn rumble(&self, strength: f32, duration: Duration) {
bf7b5671 154 if let Some(h) = &self.haptic {
902b2b31 155 h.borrow_mut().rumble_play(strength, duration.whole_milliseconds() as u32);
bf7b5671
TW
156 }
157 }
158}
159
160//#[derive(Debug)]
161pub struct ControllerManager {
162 pub joystick: JoystickSubsystem,
163 haptic: Rc<HapticSubsystem>,
164 pub controllers: HashMap<u32, Rc<RefCell<Controller>>>,
3f344b63
TW
165}
166
167impl ControllerManager {
bf7b5671
TW
168 pub fn new(joystick: JoystickSubsystem, haptic: HapticSubsystem) -> Self {
169 joystick.set_event_state(true);
b0566120 170 let mut c = ControllerManager {
bf7b5671 171 joystick,
3f344b63 172 haptic: Rc::new(haptic),
b0566120
TW
173 controllers: HashMap::new(),
174 };
175 c.init();
176 c
177 }
178
179 fn init(&mut self) {
bf7b5671 180 for i in 0..self.joystick.num_joysticks().unwrap() {
b0566120 181 self.add_device(i);
3f344b63
TW
182 }
183 }
184
902b2b31 185 pub fn update(&mut self, dt: Duration) {
bf7b5671
TW
186 self.controllers.iter().for_each(|(_, v)| v.borrow_mut().update(dt));
187 }
188
3f344b63
TW
189 pub fn handle_event(&mut self, event: &Event) {
190 match event {
bf7b5671
TW
191 Event::JoyDeviceAdded { which, .. } => { self.add_device(*which) }
192 Event::JoyDeviceRemoved { which, .. } => { self.remove_device(*which) }
193 Event::JoyButtonDown { which, button_idx, .. } => { println!("device {} button {} down!", which, button_idx) }
194 Event::JoyButtonUp { which, button_idx, .. } => { println!("device {} button {} up!", which, button_idx) }
195 Event::JoyAxisMotion { which, axis_idx, .. } => { println!("device {} axis motion {}!", which, axis_idx) }
3f344b63
TW
196 _ => {}
197 }
198 }
199
bf7b5671 200 fn add_device(&mut self, id: u32) {
3f344b63 201 println!("device added ({})!", id);
bf7b5671
TW
202 let mut device = self.joystick.open(id).unwrap();
203 println!("opened {}", device.name());
ca99d4d7
TW
204
205 /*
206 note about set_rumble (for dualshock 3 at least):
207 the active range for the low frequency is from 65536/4 to 65536 and escalates in large steps throughout the range
208 the active range for the high frequency is from 256 to 65536 and effect is the same throughout the whole range
209 */
bf7b5671 210 let haptic = match device.set_rumble(0, 256, 100) {
3f344b63
TW
211 Ok(_) => self.haptic.open_from_joystick_id(id).ok(),
212 Err(_) => None
213 };
214
b0566120
TW
215 if self.controllers.contains_key(&id) {
216 return;
217 }
218
bf7b5671 219 let detached = self.controllers.values().find(|c| !c.borrow().device.attached());
ca99d4d7
TW
220 match detached {
221 Some(c) => {
222 let mut c = c.borrow_mut();
bf7b5671 223 c.device = device;
ca99d4d7
TW
224 c.haptic = haptic.map(|h| Rc::new(RefCell::new(h)));
225 }
226 None => {
bf7b5671 227 let c = Rc::new(RefCell::new(Controller::new(device, haptic.map(|h| Rc::new(RefCell::new(h))))));
b0566120 228 self.controllers.insert(id, c);
ca99d4d7
TW
229 }
230 };
3f344b63
TW
231 }
232
bf7b5671 233 fn remove_device(&mut self, id: i32) {
3f344b63 234 println!("device removed ({})!", id);
ca99d4d7 235 // TODO
3f344b63
TW
236 }
237}