use crate::{BindingError, BindingTypes, Bindings, InputSystemDesc};
use amethyst_config::{Config, ConfigError};
use amethyst_core::{
ecs::prelude::{DispatcherBuilder, World},
SystemBundle, SystemDesc,
};
use amethyst_error::Error;
use derivative::Derivative;
use std::{error, fmt, path::Path};
#[cfg(feature = "sdl_controller")]
use crate::sdl_events_system::ControllerMappings;
#[derive(Debug, Derivative)]
#[derivative(Default(bound = ""))]
pub struct InputBundle<T: BindingTypes> {
bindings: Option<Bindings<T>>,
#[cfg(feature = "sdl_controller")]
controller_mappings: Option<ControllerMappings>,
}
impl<T: BindingTypes> InputBundle<T> {
pub fn new() -> Self {
Default::default()
}
pub fn with_bindings(mut self, bindings: Bindings<T>) -> Self {
self.bindings = Some(bindings);
self
}
pub fn with_bindings_from_file<P: AsRef<Path>>(
self,
file: P,
) -> Result<Self, BindingsFileError<T>>
where
Bindings<T>: Config,
{
let mut bindings = Bindings::load(file)?;
bindings.check_invariants()?;
Ok(self.with_bindings(bindings))
}
#[cfg(feature = "sdl_controller")]
pub fn with_sdl_controller_mappings(mut self, mappings: String) -> Self {
self.controller_mappings = Some(ControllerMappings::FromString(mappings));
self
}
#[cfg(feature = "sdl_controller")]
pub fn with_sdl_controller_mappings_from_file<P: AsRef<Path>>(mut self, file: P) -> Self {
use std::path::PathBuf;
let path_buf = PathBuf::from(file.as_ref());
self.controller_mappings = Some(ControllerMappings::FromPath(path_buf));
self
}
}
impl<'a, 'b, T: BindingTypes> SystemBundle<'a, 'b> for InputBundle<T> {
fn build(
self,
world: &mut World,
builder: &mut DispatcherBuilder<'a, 'b>,
) -> Result<(), Error> {
#[cfg(feature = "sdl_controller")]
{
use super::SdlEventsSystem;
builder.add_thread_local(
SdlEventsSystem::<T>::new(world, self.controller_mappings).unwrap(),
);
}
builder.add(
InputSystemDesc::<T>::new(self.bindings).build(world),
"input_system",
&[],
);
Ok(())
}
}
#[derive(Derivative)]
#[derivative(Debug(bound = ""))]
pub enum BindingsFileError<T: BindingTypes> {
ConfigError(ConfigError),
BindingError(BindingError<T>),
}
impl<T: BindingTypes> fmt::Display for BindingsFileError<T>
where
T::Axis: fmt::Display,
T::Action: fmt::Display,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
BindingsFileError::ConfigError(..) => write!(f, "Configuration error"),
BindingsFileError::BindingError(..) => write!(f, "Binding error"),
}
}
}
impl<T: BindingTypes> error::Error for BindingsFileError<T>
where
T::Axis: fmt::Display,
T::Action: fmt::Display,
{
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match self {
BindingsFileError::ConfigError(ref e) => Some(e),
BindingsFileError::BindingError(ref e) => Some(e),
}
}
}
impl<T: BindingTypes> From<BindingError<T>> for BindingsFileError<T> {
fn from(error: BindingError<T>) -> Self {
BindingsFileError::BindingError(error)
}
}
impl<T: BindingTypes> From<ConfigError> for BindingsFileError<T> {
fn from(error: ConfigError) -> Self {
BindingsFileError::ConfigError(error)
}
}