1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
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_no_fallback(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)
}
}