Fleshed out the controller
[kaka/rust-sdl-test.git] / src / core / controller.rs
... / ...
CommitLineData
1use sdl2::JoystickSubsystem;
2use common::Nanoseconds;
3use common::Radians;
4use common::Point2D;
5use sdl2::HapticSubsystem;
6use sdl2::event::Event;
7use sdl2::haptic::Haptic;
8use sdl2::joystick::Joystick;
9use std::cell::RefCell;
10use std::collections::HashMap;
11use std::rc::Rc;
12
13#[derive(Debug, Default)]
14pub struct Button {
15 pub time_pressed: Nanoseconds,
16 pub time_released: Nanoseconds,
17 pub is_pressed: bool,
18 pub was_pressed: bool,
19 pub toggle: bool,
20}
21
22impl Button {
23 fn update(&mut self, device: &Joystick, dt: Nanoseconds, btn: u8) {
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 {
28 self.time_pressed = 0;
29 self.toggle = !self.toggle;
30 }
31 self.time_pressed += dt;
32 true
33 }
34 Ok(false) => {
35 if self.was_pressed {
36 self.time_released = 0;
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)]
53 fn update(&mut self, device: &Joystick, _dt: Nanoseconds, axis: u8) {
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 {
70 fn update(&mut self, device: &Joystick, _dt: Nanoseconds, x_axis: u8, y_axis: u8) {
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 }
117}
118
119//#[derive(Debug)]
120pub struct Controller {
121 pub device: Joystick,
122 haptic: Option<Rc<RefCell<Haptic>>>,
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
144 pub fn update(&mut self, dt: Nanoseconds) {
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]
153 pub fn rumble(&self, strength: f32, duration_ms: u32) {
154 if let Some(h) = &self.haptic {
155 h.borrow_mut().rumble_play(strength, duration_ms);
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>>>,
165}
166
167impl ControllerManager {
168 pub fn new(joystick: JoystickSubsystem, haptic: HapticSubsystem) -> Self {
169 joystick.set_event_state(true);
170 let mut c = ControllerManager {
171 joystick,
172 haptic: Rc::new(haptic),
173 controllers: HashMap::new(),
174 };
175 c.init();
176 c
177 }
178
179 fn init(&mut self) {
180 for i in 0..self.joystick.num_joysticks().unwrap() {
181 self.add_device(i);
182 }
183 }
184
185 pub fn update(&mut self, dt: Nanoseconds) {
186 self.controllers.iter().for_each(|(_, v)| v.borrow_mut().update(dt));
187 }
188
189 pub fn handle_event(&mut self, event: &Event) {
190 match event {
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) }
196 _ => {}
197 }
198 }
199
200 fn add_device(&mut self, id: u32) {
201 println!("device added ({})!", id);
202 let mut device = self.joystick.open(id).unwrap();
203 println!("opened {}", device.name());
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 */
210 let haptic = match device.set_rumble(0, 256, 100) {
211 Ok(_) => self.haptic.open_from_joystick_id(id).ok(),
212 Err(_) => None
213 };
214
215 if self.controllers.contains_key(&id) {
216 return;
217 }
218
219 let detached = self.controllers.values().find(|c| !c.borrow().device.attached());
220 match detached {
221 Some(c) => {
222 let mut c = c.borrow_mut();
223 c.device = device;
224 c.haptic = haptic.map(|h| Rc::new(RefCell::new(h)));
225 }
226 None => {
227 let c = Rc::new(RefCell::new(Controller::new(device, haptic.map(|h| Rc::new(RefCell::new(h))))));
228 self.controllers.insert(id, c);
229 }
230 };
231 }
232
233 fn remove_device(&mut self, id: i32) {
234 println!("device removed ({})!", id);
235 // TODO
236 }
237}