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.
104 lines
3.0 KiB
Rust
104 lines
3.0 KiB
Rust
use std::ptr;
|
|
|
|
use bevy::prelude::*;
|
|
|
|
use crate::util::is_valid;
|
|
|
|
use android_looper_sys::{
|
|
ALooper_prepare,
|
|
ALooper_pollOnce
|
|
};
|
|
use android_sensor_sys::{
|
|
SensorType,
|
|
ASensorEvent,
|
|
ASensorEventQueue,
|
|
ASensorManager_getInstance,
|
|
ASensorEventQueue_getEvents,
|
|
ASensorEventQueue_hasEvents,
|
|
ASensorEventQueue_enableSensor,
|
|
ASensorEventQueue_setEventRate,
|
|
ASensorManager_createEventQueue,
|
|
ASensorManager_getDefaultSensor,
|
|
};
|
|
|
|
#[derive(Event)]
|
|
pub struct MagneticEvent {
|
|
pub x: f32,
|
|
pub y: f32,
|
|
pub z: f32
|
|
}
|
|
|
|
/* LOOPER IDs
|
|
1 is used for android_activity's main thread
|
|
2 is used for it's input handling thread
|
|
3 is supposed to be used for something too, idk
|
|
4 should be safe right? TODO: remove the stupid line at android_activity/native_activity/mod.rs:301, using 2 for now
|
|
*/
|
|
const ALOOPER_IDENTIFIER: i32 = 2;
|
|
const SENSOR_EVENT_RATE: i32 = 100000;
|
|
const ALOOPER_PREPARE_ALLOW_NON_CALLBACKS: i32 = 1;
|
|
const SENSOR_TYPE: i32 = SensorType::MagneticField as i32;
|
|
|
|
fn poll_events(queue: NonSend<*mut ASensorEventQueue>, mut events: EventWriter<MagneticEvent>) {
|
|
let queue = *queue;
|
|
let res = unsafe { ALooper_pollOnce(0, ptr::null_mut(), ptr::null_mut(), ptr::null_mut()) };
|
|
|
|
match res {
|
|
-3 => return,
|
|
-4 => panic!("Error polling once"),
|
|
ALOOPER_IDENTIFIER | -1 | -2 => {},
|
|
_ => return debug!("Polled from another Looper: {}", res)
|
|
}
|
|
if unsafe { ASensorEventQueue_hasEvents(queue) } == 0 { return }
|
|
|
|
|
|
let mut event = ASensorEvent::default();
|
|
|
|
while unsafe { ASensorEventQueue_getEvents(queue, &mut event, 1) } > 0 {
|
|
let read = unsafe {
|
|
let m = event.magnetic();
|
|
if !is_valid(m) { continue; }
|
|
m.read()
|
|
};
|
|
|
|
let result = unsafe {
|
|
let v = read.v();
|
|
if !is_valid(v) { continue; }
|
|
v.read()
|
|
};
|
|
|
|
events.send(MagneticEvent { x: result[0], y: result[1], z: result[2] });
|
|
}
|
|
}
|
|
|
|
|
|
pub struct SensorPlugin;
|
|
|
|
impl Plugin for SensorPlugin {
|
|
fn build(&self, app: &mut App) {
|
|
let manager = unsafe { ASensorManager_getInstance() };
|
|
let sensor = unsafe { ASensorManager_getDefaultSensor(manager, SENSOR_TYPE) };
|
|
let looper = unsafe { ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS) };
|
|
let queue = unsafe { ASensorManager_createEventQueue(manager, looper, ALOOPER_IDENTIFIER, None, ptr::null_mut()) };
|
|
|
|
|
|
let res = unsafe { ASensorEventQueue_enableSensor(queue, sensor) };
|
|
|
|
if res < 0 {
|
|
panic!("Couldn't enable sensor {}, error code: {}", SENSOR_TYPE, res);
|
|
} else { debug!("Enabled sensor {}", SENSOR_TYPE); }
|
|
|
|
|
|
let res = unsafe { ASensorEventQueue_setEventRate(queue, sensor, SENSOR_EVENT_RATE) };
|
|
|
|
if res < 0 {
|
|
panic!("Couldn't set sensor's event rate, error code: {}", res);
|
|
} else { debug!("Set sensor event rate to {}", SENSOR_EVENT_RATE); }
|
|
|
|
|
|
app.add_event::<MagneticEvent>()
|
|
.insert_non_send_resource(queue)
|
|
.add_systems(Update, poll_events);
|
|
}
|
|
}
|