Fleshed out the controller
[kaka/rust-sdl-test.git] / src / core / controller.rs
CommitLineData
bf7b5671
TW
1use sdl2::JoystickSubsystem;
2use common::Nanoseconds;
3use common::Radians;
4use common::Point2D;
3f344b63 5use sdl2::HapticSubsystem;
3f344b63 6use sdl2::event::Event;
bf7b5671
TW
7use sdl2::haptic::Haptic;
8use sdl2::joystick::Joystick;
9use std::cell::RefCell;
10use std::collections::HashMap;
3f344b63
TW
11use std::rc::Rc;
12
bf7b5671
TW
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 }
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
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>>>,
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
bf7b5671
TW
185 pub fn update(&mut self, dt: Nanoseconds) {
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}