1use crate::{
2 action,
3 binding::{self, ActionSet, ActionSetId, LayoutId},
4 device::{self, GamepadKind},
5 event,
6 source::{Axis, Button},
7 User,
8};
9use std::{collections::HashMap, time::Instant};
10
11pub type UserId = usize;
12
13pub struct System {
15 gamepad_input: gilrs::Gilrs,
16 users: Vec<User>,
17 actions: HashMap<action::Id, action::Action>,
18 layouts: Vec<LayoutId>,
19 action_sets: HashMap<ActionSetId, ActionSet>,
20 unassigned_devices: Vec<device::Id>,
21 device_to_user: HashMap<device::Id, UserId>,
22 disconnected_device_users: HashMap<device::Id, UserId>,
23}
24
25impl System {
26 pub fn new() -> Self {
27 Self {
28 gamepad_input: gilrs::Gilrs::new().unwrap(),
29 users: Vec::new(),
30 actions: HashMap::new(),
31 layouts: Vec::new(),
32 action_sets: HashMap::new(),
33 unassigned_devices: vec![device::Id::Mouse, device::Id::Keyboard],
34 device_to_user: HashMap::new(),
35 disconnected_device_users: HashMap::new(),
36 }
37 .initialize_gamepads()
38 }
39
40 fn initialize_gamepads(mut self) -> Self {
43 let existing_gamepad_ids = self
44 .gamepad_input
45 .gamepads()
46 .map(|(id, _)| id)
47 .collect::<Vec<_>>();
48 for id in existing_gamepad_ids {
49 self.connect_gamepad(id);
50 }
51 self
52 }
53
54 pub fn add_users(&mut self, count: usize) -> &mut Self {
57 self.users.extend((0..count).map(|_| User::default()));
58 self.assign_unused_devices();
59 self
60 }
61
62 pub fn add_action(&mut self, name: action::Id, action: action::Action) -> &mut Self {
64 self.actions.insert(name, action);
65 self
66 }
67
68 pub fn add_layout(&mut self, layout: LayoutId) -> &mut Self {
70 self.layouts.push(layout);
71 self
72 }
73
74 pub fn add_action_set(&mut self, id: ActionSetId, set: ActionSet) -> &mut Self {
76 self.action_sets.insert(id, set);
77 self
78 }
79
80 pub fn set_user_layout(&mut self, user_id: UserId, layout: LayoutId) -> &mut Self {
83 if let Some(user) = self.users.get_mut(user_id) {
84 user.set_layout(layout, &self.actions);
85 }
86 self
87 }
88
89 pub fn mark_action_set_enabled(
93 &mut self,
94 user_id: UserId,
95 set_id: ActionSetId,
96 enabled: bool,
97 ) -> &mut Self {
98 if let Some(user) = self.users.get_mut(user_id) {
99 if enabled {
100 if let Some(action_set) = self.action_sets.get(&set_id) {
101 user.enable_action_set(set_id, action_set, &self.actions);
102 }
103 } else {
104 user.disable_action_set(set_id);
105 }
106 }
107 self
108 }
109
110 pub fn enable_action_set_for_all(&mut self, id: ActionSetId) -> &mut Self {
113 if let Some(action_set) = self.action_sets.get(&id) {
114 for user in self.users.iter_mut() {
115 user.enable_action_set(id, action_set, &self.actions);
116 }
117 }
118 self
119 }
120
121 fn assign_unused_devices(&mut self) {
125 let unused_devices = self.unassigned_devices.drain(..).collect::<Vec<_>>();
126 for device in unused_devices {
127 match device {
128 device::Id::Mouse | device::Id::Keyboard => {
130 if let Some(first_user_id) = self.users.iter().position(|_| true) {
131 self.assign_device(device, first_user_id);
132 } else {
133 self.unassigned_devices.push(device);
134 }
135 }
136 device::Id::Gamepad(_, _) => {
138 if let Some(user_id) = self
139 .users
140 .iter()
141 .position(|user| !user.has_gamepad_device())
142 {
143 self.assign_device(device, user_id);
144 } else {
145 self.unassigned_devices.push(device);
146 }
147 }
148 }
149 }
150 }
151
152 fn assign_device(&mut self, device: device::Id, user_id: UserId) {
154 self.users[user_id].add_device(device);
155 self.device_to_user.insert(device, user_id);
156 if cfg!(feature = "log") {
157 log::info!(
158 target: crate::LOG,
159 "assigning {} to user {}",
160 device,
161 user_id
162 );
163 }
164 }
165
166 fn unassign_device(&mut self, device: device::Id) {
171 if let Some(user_id) = self.device_to_user.remove(&device) {
172 self.users[user_id].remove_device(device);
173 self.disconnected_device_users.insert(device, user_id);
174 if cfg!(feature = "log") {
175 log::info!(
176 target: crate::LOG,
177 "unassigning {} from user {}",
178 device,
179 user_id
180 );
181 }
182 } else {
183 self.unassigned_devices.push(device);
184 }
185 }
186
187 fn get_gamepad_kind(&self, _id: &gilrs::GamepadId) -> GamepadKind {
188 GamepadKind::DualAxisGamepad
193 }
194
195 fn connect_gamepad(&mut self, id: gilrs::GamepadId) {
203 let device = device::Id::Gamepad(self.get_gamepad_kind(&id), id);
204
205 if let Some(user_id) = self.disconnected_device_users.remove(&device) {
206 if !self.users[user_id].has_gamepad_device() {
207 self.assign_device(device, user_id);
208 return;
209 }
210 }
211
212 if let Some(user_id) = self
213 .users
214 .iter()
215 .position(|user| !user.has_gamepad_device())
216 {
217 self.assign_device(device, user_id);
218 return;
219 }
220
221 self.unassigned_devices.push(device);
222 }
223
224 fn disconnect_gamepad(&mut self, id: gilrs::GamepadId) {
226 self.unassign_device(device::Id::Gamepad(self.get_gamepad_kind(&id), id));
227 }
228
229 fn read_gamepad_events(&mut self) {
232 use gilrs::EventType;
233 use std::convert::TryFrom;
234 while let Some(gilrs::Event {
235 id,
236 event, ..
238 }) = self.gamepad_input.next_event()
239 {
240 let time = Instant::now();
241 let gamepad_kind = self.get_gamepad_kind(&id);
242 let device = device::Id::Gamepad(gamepad_kind, id);
243 match event {
244 EventType::Connected => self.connect_gamepad(id),
247 EventType::Disconnected => self.disconnect_gamepad(id),
249 EventType::Dropped => {}
251 EventType::ButtonPressed(btn, _) => {
253 if let Some(button) = Button::try_from(btn).ok() {
254 self.process_event(
255 device,
256 event::Event::new(
257 binding::Source::Gamepad(
258 gamepad_kind,
259 binding::Gamepad::Button(button),
260 ),
261 event::State::ButtonState(event::ButtonState::Pressed),
262 ),
263 time,
264 );
265 }
266 }
267 EventType::ButtonReleased(btn, _) => {
269 if let Some(button) = Button::try_from(btn).ok() {
270 self.process_event(
271 device,
272 event::Event::new(
273 binding::Source::Gamepad(
274 gamepad_kind,
275 binding::Gamepad::Button(button),
276 ),
277 event::State::ButtonState(event::ButtonState::Released),
278 ),
279 time,
280 );
281 }
282 }
283 EventType::ButtonRepeated(_btn, _) => {}
285 EventType::ButtonChanged(btn, value, _) => {
287 if let Some(button) = Button::try_from(btn).ok() {
288 self.process_event(
289 device,
290 event::Event::new(
291 binding::Source::Gamepad(
292 gamepad_kind,
293 binding::Gamepad::Button(button),
294 ),
295 event::State::ValueChanged(value),
296 ),
297 time,
298 );
299 }
300 }
301 EventType::AxisChanged(axis, value, _) => {
303 if let Some(axis) = Axis::try_from(axis).ok() {
304 self.process_event(
305 device,
306 event::Event::new(
307 binding::Source::Gamepad(
308 gamepad_kind,
309 binding::Gamepad::Axis(axis),
310 ),
311 event::State::ValueChanged(value),
312 ),
313 time,
314 );
315 }
316 }
317 }
318 }
319 }
320
321 pub fn send_event(&mut self, source: event::Source, event: event::Event) {
325 self.process_event(
326 match source {
327 event::Source::Mouse => device::Id::Mouse,
328 event::Source::Keyboard => device::Id::Keyboard,
329 },
330 event,
331 Instant::now(),
332 );
333 }
334
335 fn process_event(&mut self, device: device::Id, event: event::Event, time: Instant) {
337 for event in self.parse_event(event) {
338 self.update_user_actions(device, event, time);
339 }
340 }
341
342 fn parse_event(&mut self, event: event::Event) -> Vec<event::Event> {
346 let mut events = vec![event.clone()];
347 if let event::Event {
348 source: binding::Source::Gamepad(kind, binding::Gamepad::Button(Button::FaceBottom)),
349 ..
350 } = event
351 {
352 events.push(event::Event {
353 source: binding::Source::Gamepad(
354 kind,
355 binding::Gamepad::Button(Button::VirtualConfirm),
356 ),
357 ..event
358 });
359 }
360 if let event::Event {
361 source: binding::Source::Gamepad(kind, binding::Gamepad::Button(Button::FaceRight)),
362 ..
363 } = event
364 {
365 events.push(event::Event {
366 source: binding::Source::Gamepad(
367 kind,
368 binding::Gamepad::Button(Button::VirtualDeny),
369 ),
370 ..event
371 });
372 }
373 events
374 }
375
376 fn update_user_actions(&mut self, device: device::Id, event: event::Event, time: Instant) {
378 if let Some(user_id) = self.device_to_user.get(&device) {
379 if let Some(user) = self.users.get_mut(*user_id) {
380 user.process_event(&event, &time);
381 }
382 }
383 }
384
385 pub fn update(&mut self) {
387 self.read_gamepad_events();
388 let time = Instant::now();
389 for user in self.users.iter_mut() {
390 user.update(&time);
391 }
392 }
393
394 pub fn get_user_ids(&self) -> Vec<UserId> {
396 (0..self.users.len()).collect()
397 }
398
399 pub fn get_user_action(
403 &self,
404 user_id: UserId,
405 action_id: action::Id,
406 ) -> Option<&action::State> {
407 self.users
408 .get(user_id)
409 .map(|user| user.get_action(action_id))
410 .flatten()
411 }
412}