azul_layout/managers/
sensors.rs1use alloc::vec::Vec;
19
20use azul_core::dom::DomNodeId;
21use azul_core::events::{
22 EventData, EventProvider, EventSource as CoreEventSource, EventType, SyntheticEvent,
23};
24use azul_core::task::Instant;
25pub use azul_core::sensors::{SensorKind, SensorReading};
26
27#[derive(Debug, Clone, PartialEq, Default)]
30pub struct SensorManager {
31 pub accelerometer: Option<SensorReading>,
33 pub gyroscope: Option<SensorReading>,
35 pub magnetometer: Option<SensorReading>,
37 pub pending_event: bool,
41}
42
43impl SensorManager {
44 pub fn new() -> Self {
45 Self::default()
46 }
47
48 pub fn reading(&self, kind: SensorKind) -> Option<SensorReading> {
50 match kind {
51 SensorKind::Accelerometer => self.accelerometer,
52 SensorKind::Gyroscope => self.gyroscope,
53 SensorKind::Magnetometer => self.magnetometer,
54 }
55 }
56
57 pub fn set_reading(&mut self, reading: SensorReading) -> bool {
61 let slot = match reading.kind {
62 SensorKind::Accelerometer => &mut self.accelerometer,
63 SensorKind::Gyroscope => &mut self.gyroscope,
64 SensorKind::Magnetometer => &mut self.magnetometer,
65 };
66 let changed = match slot {
67 Some(prev) => !reading_bitwise_eq(prev, &reading),
68 None => true,
69 };
70 *slot = Some(reading);
71 if changed {
72 self.pending_event = true;
73 }
74 changed
75 }
76
77 pub fn clear_pending_event(&mut self) {
80 self.pending_event = false;
81 }
82}
83
84impl EventProvider for SensorManager {
85 fn get_pending_events(&self, timestamp: Instant) -> Vec<SyntheticEvent> {
89 if self.pending_event {
90 alloc::vec![SyntheticEvent::new(
91 EventType::SensorChanged,
92 CoreEventSource::User,
93 DomNodeId::ROOT,
94 timestamp,
95 EventData::None,
96 )]
97 } else {
98 Vec::new()
99 }
100 }
101}
102
103fn reading_bitwise_eq(a: &SensorReading, b: &SensorReading) -> bool {
104 a.kind == b.kind
105 && a.x.to_bits() == b.x.to_bits()
106 && a.y.to_bits() == b.y.to_bits()
107 && a.z.to_bits() == b.z.to_bits()
108 && a.timestamp_ms == b.timestamp_ms
109}
110
111static PENDING_READINGS: std::sync::Mutex<Vec<SensorReading>> =
120 std::sync::Mutex::new(Vec::new());
121
122pub fn push_sensor_reading(reading: SensorReading) {
125 let mut q = PENDING_READINGS.lock().unwrap_or_else(|e| e.into_inner());
126 q.push(reading);
127}
128
129pub fn drain_sensor_readings() -> Vec<SensorReading> {
133 let mut q = PENDING_READINGS.lock().unwrap_or_else(|e| e.into_inner());
134 core::mem::take(&mut *q)
135}
136
137#[cfg(test)]
138mod tests {
139 use super::*;
140
141 fn r(kind: SensorKind, x: f32, y: f32, z: f32) -> SensorReading {
142 SensorReading {
143 kind,
144 x,
145 y,
146 z,
147 timestamp_ms: 0,
148 }
149 }
150
151 #[test]
152 fn manager_defaults_to_no_readings() {
153 let mgr = SensorManager::new();
154 assert_eq!(mgr.reading(SensorKind::Accelerometer), None);
155 assert_eq!(mgr.reading(SensorKind::Gyroscope), None);
156 assert_eq!(mgr.reading(SensorKind::Magnetometer), None);
157 }
158
159 #[test]
160 fn set_reading_routes_by_kind_and_flags_change() {
161 let mut mgr = SensorManager::new();
162 assert!(mgr.set_reading(r(SensorKind::Accelerometer, 0.0, 0.0, 9.81)));
163 assert!(mgr.reading(SensorKind::Accelerometer).is_some());
165 assert_eq!(mgr.reading(SensorKind::Gyroscope), None);
166 assert!(!mgr.set_reading(r(SensorKind::Accelerometer, 0.0, 0.0, 9.81)));
168 assert!(mgr.set_reading(r(SensorKind::Accelerometer, 1.0, 0.0, 9.81)));
170 assert!(mgr.set_reading(r(SensorKind::Gyroscope, 0.1, 0.0, 0.0)));
172 assert_eq!(
173 mgr.reading(SensorKind::Gyroscope).map(|r| r.x),
174 Some(0.1)
175 );
176 }
177
178 #[test]
179 fn magnitude_of_resting_accelerometer() {
180 let g = r(SensorKind::Accelerometer, 0.0, 0.0, 9.81);
181 assert!((g.magnitude() - 9.81).abs() < 1e-4);
182 }
183
184 #[test]
185 fn readings_round_trip_through_manager() {
186 let _ = drain_sensor_readings();
187
188 push_sensor_reading(r(SensorKind::Accelerometer, 1.0, 2.0, 3.0));
189 push_sensor_reading(r(SensorKind::Accelerometer, 4.0, 5.0, 6.0)); push_sensor_reading(r(SensorKind::Magnetometer, 20.0, 0.0, 40.0));
191 let drained = drain_sensor_readings();
192 assert_eq!(drained.len(), 3, "all parked readings drain in order");
193
194 let mut mgr = SensorManager::new();
195 for reading in &drained {
196 mgr.set_reading(*reading);
197 }
198 assert_eq!(
199 mgr.reading(SensorKind::Accelerometer).map(|r| r.x),
200 Some(4.0),
201 "the last accelerometer reading wins"
202 );
203 assert_eq!(
204 mgr.reading(SensorKind::Magnetometer).map(|r| r.z),
205 Some(40.0)
206 );
207
208 assert!(drain_sensor_readings().is_empty());
209 }
210}