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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
use crate::audio::*;
use crate::controller::*;
use crate::user::*;
/// The Dive Application Context.
pub struct App<T> {
// User
user: User,
// Audio
mic: MicrophoneSystem,
speaker: SpeakerSystem,
// Store
file: T,
changed: bool,
// Controller
controller_port: ControllerPort,
axis: [f32; 8],
btns: [bool; 16],
}
impl<T> App<T> {
/// Create a new Application.
pub fn new(file: T) -> App<T> {
App {
user: User::new(),
mic: MicrophoneSystem::new(SampleRate::Normal).unwrap(),
speaker: SpeakerSystem::new(SampleRate::Normal).unwrap(),
file,
changed: false,
controller_port: ControllerPort::new(),
axis: [0.0; 8],
btns: [false; 16],
}
}
/// Get user information.
pub fn user(&self) -> &User {
&self.user
}
/// Get the file data.
pub fn file(&mut self) -> &mut T {
&mut self.file
}
/// Fetch a resource.
pub fn fetch<U>(&mut self, res: &str) -> Option<U>
where
for<'de> U: serde::Deserialize<'de>,
{
stronghold::fetch(res)
}
/// Load file `res` from `zip`.
pub fn open(&mut self, zip: &str, res: &str) -> Option<()>
where
for<'de> T: serde::Deserialize<'de>,
{
self.file = stronghold::load(zip, res)?;
Some(())
}
/// File data has changed. Next call to `sync()` will save the file.
pub fn edit(&mut self) {
self.changed = true;
}
/// Save file `res` in `zip` only if `edit()` has been called since last change.
pub fn sync(&mut self, zip: &str, res: &str)
where
T: serde::Serialize,
{
if self.changed {
stronghold::save(zip, res, &self.file);
self.changed = false;
}
}
/// Record Audio. Callback's parameters are (microphone ID, left sample, right sample).
pub fn record(&mut self, callback: &mut FnMut(usize, i16, i16)) {
self.mic.record(callback);
}
/// Play Audio. Callback generates audio samples sent directly to speakers.
pub fn play(&mut self, callback: &mut FnMut() -> AudioSample) {
self.speaker.play(callback);
}
/// Return the number of controllers.
pub fn controller_update(&mut self) -> u16 {
self.controller_port.update()
}
/// Get the state of a controller from the requested controller layout.
pub fn controller_get(&mut self, id: u16, layout: &ControllerLayout) -> (&[f32], &[bool]) {
let mut state = self.controller_port.get(id);
let mut i_axis = 0;
let mut i_btns = 0;
for axis in 0..layout.axis.len() {
match layout.axis[axis] {
Axis::JoyXY => {
// TODO: Fallback.
let (x, y) = state.joy().unwrap_or((0.0, 0.0));
self.axis[i_axis] = x;
i_axis += 1;
self.axis[i_axis] = y;
i_axis += 1;
}
Axis::CamXY => {
// TODO: Fallback.
let (x, y) = state.cam().unwrap_or((0.0, 0.0));
self.axis[i_axis] = x;
i_axis += 1;
self.axis[i_axis] = y;
i_axis += 1;
}
Axis::Lrt => {
// TODO: Fallback.
let (x, y) = state.lrt().unwrap_or((0.0, 0.0));
self.axis[i_axis] = x;
i_axis += 1;
self.axis[i_axis] = y;
i_axis += 1;
}
Axis::Pitch => {
// TODO: Fallback.
let x = state.pitch().unwrap_or(0.0);
self.axis[i_axis] = x;
i_axis += 1;
}
Axis::Yaw => {
// let x = state.yaw().unwrap_or(0.0);
// TODO: Not supported yet.
self.axis[i_axis] = 0.0;
i_axis += 1;
}
}
}
for btn in 0..layout.btns.len() {
match layout.btns[btn] {
Btns::Abxy => {
self.btns[i_btns] = state.btn(Btn::A).unwrap_or(false);
i_btns += 1;
self.btns[i_btns] = state.btn(Btn::B).unwrap_or(false);
i_btns += 1;
self.btns[i_btns] = state.btn(Btn::X).unwrap_or(false);
i_btns += 1;
self.btns[i_btns] = state.btn(Btn::Y).unwrap_or(false);
i_btns += 1;
}
Btns::Dpad => {
self.btns[i_btns] = state.btn(Btn::Up).unwrap_or(false);
i_btns += 1;
self.btns[i_btns] = state.btn(Btn::Down).unwrap_or(false);
i_btns += 1;
self.btns[i_btns] = state.btn(Btn::Left).unwrap_or(false);
i_btns += 1;
self.btns[i_btns] = state.btn(Btn::Right).unwrap_or(false);
i_btns += 1;
}
Btns::Quit => {
self.btns[i_btns] = state.btn(Btn::E).unwrap_or(false);
i_btns += 1;
}
Btns::Menu => {
self.btns[i_btns] = state.btn(Btn::F).unwrap_or(false);
i_btns += 1;
}
Btns::Wz => {
self.btns[i_btns] = state.btn(Btn::W).unwrap_or(false);
i_btns += 1;
self.btns[i_btns] = state.btn(Btn::Z).unwrap_or(false);
i_btns += 1;
}
Btns::Lr => {
self.btns[i_btns] = state.btn(Btn::L).unwrap_or(false);
i_btns += 1;
self.btns[i_btns] = state.btn(Btn::R).unwrap_or(false);
i_btns += 1;
}
Btns::Dc => {
self.btns[i_btns] = state.btn(Btn::D).unwrap_or(false);
i_btns += 1;
self.btns[i_btns] = state.btn(Btn::C).unwrap_or(false);
i_btns += 1;
}
}
}
(&self.axis[..i_axis], &self.btns[..i_btns])
}
}