From 1de9cea397d43837961da157e64b14aee4290fe4 Mon Sep 17 00:00:00 2001 From: Torge Matthies Date: Fri, 28 Jun 2024 11:41:25 +0200 Subject: [PATCH] feat: openxr battery status --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/backend/openxr/input.rs | 64 ++++++++++++++++++++++++++++++++++++- src/backend/openxr/mod.rs | 6 ++++ 4 files changed, 71 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4c250efa..66e1b2cd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2044,7 +2044,7 @@ dependencies = [ [[package]] name = "libmonado-rs" version = "0.1.0" -source = "git+https://github.com/technobaboo/libmonado-rs?rev=bf1bcf7#bf1bcf74d496679fe51b6ca609f36be7f39d857e" +source = "git+https://github.com/technobaboo/libmonado-rs?rev=d5d8877#d5d88775b7a6286b796ba514faa9f4aaa3f74922" dependencies = [ "bindgen", "cmake", diff --git a/Cargo.toml b/Cargo.toml index 0d6266c7..e5518ce2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -55,7 +55,7 @@ thiserror = "1.0.61" vulkano = { git = "https://github.com/vulkano-rs/vulkano", rev = "b9f3e89" } vulkano-shaders = { git = "https://github.com/vulkano-rs/vulkano", rev = "b9f3e89" } wlx-capture = { git = "https://github.com/galister/wlx-capture", tag = "v0.3.12", default-features = false } -libmonado-rs = { git = "https://github.com/technobaboo/libmonado-rs", rev = "bf1bcf7", optional = true } +libmonado-rs = { git = "https://github.com/technobaboo/libmonado-rs", rev = "d5d8877", optional = true } winit = { version = "0.30.0", optional = true } xdg = "2.5.2" log-panics = { version = "2.1.0", features = ["with-backtrace"] } diff --git a/src/backend/openxr/input.rs b/src/backend/openxr/input.rs index 5f0e47e2..75935fa6 100644 --- a/src/backend/openxr/input.rs +++ b/src/backend/openxr/input.rs @@ -7,9 +7,10 @@ use std::{ use glam::{bool, Affine3A, Quat, Vec3}; use openxr::{self as xr, Quaternionf, Vector3f}; use serde::{Deserialize, Serialize}; +use libmonado_rs::{Monado, Device}; use crate::{ - backend::input::{Haptics, Pointer}, + backend::input::{Haptics, Pointer, TrackedDevice, TrackedDeviceRole}, config_io, state::{AppSession, AppState}, }; @@ -208,6 +209,67 @@ impl OpenXrInputSource { } Ok(()) } + + fn update_device_battery_status( + device: &mut Device, + role: TrackedDeviceRole, + app: &mut AppState + ) { + if let Ok(status) = device.battery_status() { + if status.present { + app.input_state.devices.push(TrackedDevice { + soc: Some(status.charge), + charging: status.charging, + role, + }); + log::debug!("Device {} role {:#?}: {:.0}% (charging {})", device.index, role, + status.charge * 100.0f32, status.charging); + } + } + } + + pub fn update_devices(&mut self, app: &mut AppState, monado: &mut Monado) { + app.input_state.devices.clear(); + + let roles = [ + ("head", TrackedDeviceRole::Hmd), + ("eyes", TrackedDeviceRole::None), + ("left", TrackedDeviceRole::LeftHand), + ("right", TrackedDeviceRole::RightHand), + ("gamepad", TrackedDeviceRole::None), + ("hand-tracking-left", TrackedDeviceRole::LeftHand), + ("hand-tracking-right", TrackedDeviceRole::RightHand), + ]; + let mut seen = Vec::::with_capacity(32); + for (mnd_role, wlx_role) in roles { + let device = monado.device_from_role(mnd_role); + if let Ok(mut device) = device { + if !seen.contains(&device.index) { + seen.push(device.index); + Self::update_device_battery_status(&mut device, wlx_role, app); + } + } + } + if let Ok(devices) = monado.devices() { + for mut device in devices { + if !seen.contains(&device.index) { + let role = if device.id >= 4 && device.id <= 8 { + TrackedDeviceRole::Tracker + } else { + TrackedDeviceRole::None + }; + Self::update_device_battery_status(&mut device, role, app); + } + } + } + + app.input_state.devices.sort_by(|a, b| { + (a.soc.is_none() as u8) + .cmp(&(b.soc.is_none() as u8)) + .then((a.role as u8).cmp(&(b.role as u8))) + .then(a.soc.unwrap_or(999.).total_cmp(&b.soc.unwrap_or(999.))) + }); + } } impl OpenXrHand { diff --git a/src/backend/openxr/mod.rs b/src/backend/openxr/mod.rs index 52446b95..d1de4687 100644 --- a/src/backend/openxr/mod.rs +++ b/src/backend/openxr/mod.rs @@ -146,6 +146,7 @@ pub fn openxr_run(running: Arc, show_by_default: bool) -> Result<(), let mut session_running = false; let mut event_storage = xr::EventDataBuffer::new(); + let mut next_device_update = Instant::now(); let mut due_tasks = VecDeque::with_capacity(4); let mut main_session_visible = false; @@ -210,6 +211,11 @@ pub fn openxr_run(running: Arc, show_by_default: bool) -> Result<(), } } + if next_device_update <= Instant::now() { + input_source.update_devices(&mut app_state, monado.as_mut().unwrap()); + next_device_update = Instant::now() + Duration::from_secs(30); + } + if !session_running { std::thread::sleep(Duration::from_millis(100)); continue 'main_loop;