use serde::{Deserialize, Serialize}; use std::collections::HashMap; use crate::types::{InputCause, InputTypeFlags, ProcessingResult}; pub mod types; #[cfg(feature="backend_piston")] pub mod backend_piston; #[cfg(feature="backend_gilrs")] pub mod backend_gilrs; #[cfg(test)] mod tests; #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] #[serde(transparent)] struct EventType(u128); impl EventType { fn new(rt: u64, rv: u64) -> Self { EventType { 0: (rt as u128).rotate_left(64) + u128::from(rv) } } } /// Converts backend events to more "generic" and serializable /// event types. This usually means stripping down needless data /// and making the result small (u64). For example, for keyboard key mapping /// we only care about the event's "identifier" for the key and it's state (pressed/released) /// If there's more info in the backend event we discard that as it could be tied to the /// instance rather than the "type of input" such as event_id sequence or such. /// This should be typically implemented by the prongs-backend- sub-cargos. trait ToEventType where TControllerID: Copy + PartialEq + Serialize { fn to_raw(&self) -> Option; fn controller_id(&self) -> Option; fn filter_for_assignment(&self, iaf: InputTypeFlags) -> bool; fn get_cause(&self) -> Option; } type KeyMap = HashMap; const TYPICAL_MAPPING_SIZE: usize = 255; #[derive(Serialize, Deserialize)] struct Schema where TEventType: ToEventType, TControllerID: Copy + PartialEq + Serialize, TUserAction: Clone + Serialize, { name: String, player_id: Option, controller_id: Option, keymap: KeyMap, #[serde(skip)] _phantom: std::marker::PhantomData, } impl Schema where TEventType: ToEventType, TControllerID: Copy + PartialEq + Serialize, TUserAction: Clone + Serialize, { fn new(name: &str) -> Self { Schema { name: name.to_string(), keymap: KeyMap::with_capacity(TYPICAL_MAPPING_SIZE), player_id: None, controller_id: None, _phantom: std::marker::PhantomData, } } fn assign_controller(&mut self, event: &TEventType, iaf: InputTypeFlags) -> bool { let event_controller_id = event.controller_id(); if event_controller_id != self.controller_id && event_controller_id.is_some() && event.filter_for_assignment(iaf) { self.controller_id = event.controller_id(); return true } false } fn assign_input(&mut self, event: &TEventType, action: TUserAction, iaf: InputTypeFlags) -> bool { if event.filter_for_assignment(iaf) { if let Some(event_type) = event.to_raw() { self.keymap.insert(event_type, action); self.assign_controller(event, iaf); return true } } false } fn process_event(&mut self, event: &TEventType) -> Option> { if let Some(event_type) = event.to_raw() { if let Some(action) = self.keymap.get(&event_type) { if self.controller_id.is_some() && self.controller_id != event.controller_id() { return None } return Some(ProcessingResult { action: action.clone(), player_id: self.player_id, cause: event.get_cause(), }); } } None } fn set_player_id(&mut self, player_id: Option) { self.player_id = player_id; } }