You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

133 lines
4.1 KiB
Rust

use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use crate::types::{InputCause, InputTypeFlags, ProcessingResult};
pub mod types;
// error out specifically if no backend is chosen
#[cfg(not(any(feature="backend_piston", feature="backend_gilrs")))]
compile_error!("No backend selected, use features=<backend> in Cargo.toml or --features <backend> when building directly.");
#[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-<name> sub-cargos.
trait ToEventType<TControllerID>
where TControllerID: Copy + PartialEq + Serialize
{
fn to_raw(&self) -> Option<EventType>;
fn controller_id(&self) -> Option<TControllerID>;
fn filter_for_assignment(&self, iaf: InputTypeFlags) -> bool;
fn get_cause(&self) -> Option<InputCause>;
}
type KeyMap<TUserAction> = HashMap<EventType, TUserAction>;
const TYPICAL_MAPPING_SIZE: usize = 255;
#[derive(Serialize, Deserialize)]
struct Schema<TEventType, TControllerID, TUserAction>
where TEventType: ToEventType<TControllerID>,
TControllerID: Copy + PartialEq + Serialize,
TUserAction: Clone + Serialize,
{
name: String,
player_id: Option<usize>,
controller_id: Option<TControllerID>,
keymap: KeyMap<TUserAction>,
#[serde(skip)]
_phantom: std::marker::PhantomData<TEventType>,
}
impl<TEventType, TControllerID, TUserAction> Schema<TEventType, TControllerID, TUserAction>
where TEventType: ToEventType<TControllerID>,
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<ProcessingResult<TUserAction>> {
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<usize>) {
self.player_id = player_id;
}
}