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) { 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::() .insert_non_send_resource(queue) .add_systems(Update, poll_events); } }