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

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);
}
}