improve error handling

This commit is contained in:
galister
2024-02-18 22:24:36 +01:00
parent 615470aa92
commit 63b43c0e59
17 changed files with 517 additions and 611 deletions

View File

@@ -6,6 +6,8 @@ use std::{
use glam::{Affine3A, Vec2, Vec3A};
use idmap::IdMap;
use openxr as xr;
use thiserror::Error;
use crate::{
overlays::{
@@ -18,11 +20,19 @@ use crate::{
use super::overlay::{OverlayData, OverlayState};
#[derive(Error, Debug)]
pub enum BackendError {
#[error("backend not supported")]
NotSupported,
#[cfg(feature = "openxr")]
#[error("openxr error {0}")]
OpenXrError(#[from] xr::sys::Result),
#[error("shutdown")]
Shutdown,
#[error("restart")]
Restart,
Fatal,
#[error("fatal")]
Fatal(#[from] anyhow::Error),
}
pub struct OverlayContainer<T>
@@ -191,6 +201,7 @@ impl TaskContainer {
break;
}
// Safe unwrap because we peeked.
dest_buf.push_back(self.tasks.pop().unwrap().task);
}
}

View File

@@ -395,10 +395,10 @@ impl Pointer {
}
}
hits.sort_by(|a, b| a.dist.partial_cmp(&b.dist).unwrap());
hits.sort_by(|a, b| a.dist.total_cmp(&b.dist));
for hit in hits.iter() {
let overlay = overlays.get_by_id(hit.overlay).unwrap(); // this is safe
let overlay = overlays.get_by_id(hit.overlay).unwrap(); // safe because we just got the id from the overlay
let uv = overlay
.state
@@ -447,27 +447,32 @@ impl Pointer {
O: Default,
{
if self.now.grab {
let grab_data = self.interaction.grabbed.as_mut().unwrap();
if self.now.click {
self.interaction.mode = PointerMode::Special;
let cur_scale = overlay.state.transform.x_axis.length();
if cur_scale < 0.1 && self.now.scroll > 0.0 {
return;
} else if cur_scale > 20. && self.now.scroll < 0.0 {
return;
}
if let Some(grab_data) = self.interaction.grabbed.as_mut() {
if self.now.click {
self.interaction.mode = PointerMode::Special;
let cur_scale = overlay.state.transform.x_axis.length();
if cur_scale < 0.1 && self.now.scroll > 0.0 {
return;
}
if cur_scale > 20. && self.now.scroll < 0.0 {
return;
}
overlay.state.transform.matrix3 = overlay
.state
.transform
.matrix3
.mul_scalar(1.0 - 0.025 * self.now.scroll);
overlay.state.transform.matrix3 = overlay
.state
.transform
.matrix3
.mul_scalar(1.0 - 0.025 * self.now.scroll);
} else {
grab_data.offset.z -= self.now.scroll * 0.05;
}
overlay.state.transform.translation = self.pose.transform_point3a(grab_data.offset);
overlay.state.realign(hmd);
overlay.state.dirty = true;
} else {
grab_data.offset.z -= self.now.scroll * 0.05;
log::error!("Grabbed overlay {} does not exist", overlay.state.id);
self.interaction.grabbed = None;
}
overlay.state.transform.translation = self.pose.transform_point3a(grab_data.offset);
overlay.state.realign(hmd);
overlay.state.dirty = true;
} else {
overlay.state.saved_point = Some(
hmd.inverse()

View File

@@ -1,5 +1,8 @@
use glam::Affine3A;
use ovr_overlay::{pose::Matrix3x4, sys::HmdMatrix34_t};
use thiserror::Error;
use crate::backend::common::BackendError;
pub trait Affine3AConvert {
fn from_affine(affine: Affine3A) -> Self;
@@ -75,3 +78,21 @@ impl Affine3AConvert for HmdMatrix34_t {
])
}
}
#[derive(Error, Debug)]
pub(super) enum OVRError {
#[error("ovr input error: {0}")]
InputError(&'static str),
}
impl From<ovr_overlay::errors::EVRInputError> for OVRError {
fn from(e: ovr_overlay::errors::EVRInputError) -> Self {
OVRError::InputError(e.description())
}
}
impl From<OVRError> for BackendError {
fn from(e: OVRError) -> Self {
BackendError::Fatal(anyhow::Error::new(e))
}
}

View File

@@ -17,16 +17,7 @@ use crate::{
state::AppState,
};
use super::helpers::Affine3AConvert;
macro_rules! result_str {
( $e:expr ) => {
match $e {
Ok(x) => Ok(x),
Err(y) => Err(y.description()),
}
};
}
use super::helpers::{Affine3AConvert, OVRError};
const SET_DEFAULT: &str = "/actions/default";
const INPUT_SOURCES: [&str; 2] = ["/user/hand/left", "/user/hand/right"];
@@ -71,34 +62,32 @@ pub(super) struct OpenVrHandSource {
}
impl OpenVrInputSource {
pub fn new(input: &mut InputManager) -> Result<Self, &'static str> {
let set_hnd = result_str!(input.get_action_set_handle(SET_DEFAULT))?;
pub fn new(input: &mut InputManager) -> Result<Self, OVRError> {
let set_hnd = input.get_action_set_handle(SET_DEFAULT)?;
let click_hnd = result_str!(input.get_action_handle(PATH_CLICK))?;
let grab_hnd = result_str!(input.get_action_handle(PATH_GRAB))?;
let scroll_hnd = result_str!(input.get_action_handle(PATH_SCROLL))?;
let alt_click_hnd = result_str!(input.get_action_handle(PATH_ALT_CLICK))?;
let show_hide_hnd = result_str!(input.get_action_handle(PATH_SHOW_HIDE))?;
let space_drag_hnd = result_str!(input.get_action_handle(PATH_SPACE_DRAG))?;
let click_modifier_right_hnd =
result_str!(input.get_action_handle(PATH_CLICK_MODIFIER_RIGHT))?;
let click_modifier_middle_hnd =
result_str!(input.get_action_handle(PATH_CLICK_MODIFIER_MIDDLE))?;
let click_hnd = input.get_action_handle(PATH_CLICK)?;
let grab_hnd = input.get_action_handle(PATH_GRAB)?;
let scroll_hnd = input.get_action_handle(PATH_SCROLL)?;
let alt_click_hnd = input.get_action_handle(PATH_ALT_CLICK)?;
let show_hide_hnd = input.get_action_handle(PATH_SHOW_HIDE)?;
let space_drag_hnd = input.get_action_handle(PATH_SPACE_DRAG)?;
let click_modifier_right_hnd = input.get_action_handle(PATH_CLICK_MODIFIER_RIGHT)?;
let click_modifier_middle_hnd = input.get_action_handle(PATH_CLICK_MODIFIER_MIDDLE)?;
let input_hnd: Vec<InputValueHandle> = INPUT_SOURCES
.iter()
.map(|path| Ok(result_str!(input.get_input_source_handle(path))?))
.collect::<Result<_, &'static str>>()?;
.map(|path| Ok((input.get_input_source_handle(path))?))
.collect::<Result<_, OVRError>>()?;
let pose_hnd: Vec<ActionHandle> = PATH_POSES
.iter()
.map(|path| Ok(result_str!(input.get_action_handle(path))?))
.collect::<Result<_, &'static str>>()?;
.map(|path| Ok((input.get_action_handle(path))?))
.collect::<Result<_, OVRError>>()?;
let haptics_hnd: Vec<ActionHandle> = PATH_HAPTICS
.iter()
.map(|path| Ok(result_str!(input.get_action_handle(path))?))
.collect::<Result<_, &'static str>>()?;
.map(|path| Ok((input.get_action_handle(path))?))
.collect::<Result<_, OVRError>>()?;
let hands: [OpenVrHandSource; 2] = array::from_fn(|i| OpenVrHandSource {
has_pose: false,
@@ -317,38 +306,29 @@ pub fn set_action_manifest(input: &mut InputManager) -> anyhow::Result<()> {
let action_path = CONFIG_ROOT_PATH.join("actions.json");
if !action_path.is_file() {
File::create(&action_path)
.unwrap()
.write_all(include_bytes!("../../res/actions.json"))
.unwrap();
File::create(&action_path)?.write_all(include_bytes!("../../res/actions.json"))?;
}
let binding_path = CONFIG_ROOT_PATH.join("actions_binding_knuckles.json");
if !binding_path.is_file() {
File::create(&binding_path)
.unwrap()
.write_all(include_bytes!("../../res/actions_binding_knuckles.json"))
.unwrap();
File::create(&binding_path)?
.write_all(include_bytes!("../../res/actions_binding_knuckles.json"))?;
}
let binding_path = CONFIG_ROOT_PATH.join("actions_binding_vive.json");
if !binding_path.is_file() {
File::create(&binding_path)
.unwrap()
.write_all(include_bytes!("../../res/actions_binding_vive.json"))
.unwrap();
File::create(&binding_path)?
.write_all(include_bytes!("../../res/actions_binding_vive.json"))?;
}
let binding_path = CONFIG_ROOT_PATH.join("actions_binding_oculus.json");
if !binding_path.is_file() {
File::create(&binding_path)
.unwrap()
.write_all(include_bytes!("../../res/actions_binding_oculus.json"))
.unwrap();
File::create(&binding_path)?
.write_all(include_bytes!("../../res/actions_binding_oculus.json"))?;
}
if let Err(e) = input.set_action_manifest(action_path.as_path()) {
bail!("Failed to set action manifest: {}", e.description());
bail!("Failed to set action manifest: {}", e);
}
Ok(())
}

View File

@@ -7,6 +7,7 @@ use std::{
time::{Duration, Instant},
};
use anyhow::{anyhow, Result};
use ovr_overlay::{
sys::{ETrackedDeviceProperty, EVRApplicationType, EVREventType},
TrackedDeviceIndex,
@@ -83,7 +84,7 @@ pub fn openvr_run(running: Arc<AtomicBool>) -> Result<(), BackendError> {
let mut state = {
let graphics = WlxGraphics::new_openvr(instance_extensions, device_extensions_fn);
AppState::from_graphics(graphics)
AppState::from_graphics(graphics)?
};
install_manifest(&mut app_mgr);
@@ -97,22 +98,17 @@ pub fn openvr_run(running: Arc<AtomicBool>) -> Result<(), BackendError> {
state.hid_provider.set_desktop_extent(overlays.extent);
if let Err(e) = set_action_manifest(&mut input_mngr) {
log::error!("{}", e.to_string());
return Err(BackendError::Fatal);
};
set_action_manifest(&mut input_mngr)?;
let Ok(mut input_source) = OpenVrInputSource::new(&mut input_mngr) else {
log::error!("Failed to initialize input");
return Err(BackendError::Fatal);
};
let mut input_source = OpenVrInputSource::new(&mut input_mngr)?;
let Ok(refresh_rate) = system_mngr.get_tracked_device_property::<f32>(
TrackedDeviceIndex::HMD,
ETrackedDeviceProperty::Prop_DisplayFrequency_Float,
) else {
log::error!("Failed to get display refresh rate");
return Err(BackendError::Fatal);
return Err(BackendError::Fatal(anyhow!(
"Failed to get HMD refresh rate"
)));
};
log::info!("HMD running @ {} Hz", refresh_rate);

View File

@@ -92,7 +92,7 @@ impl OverlayData<OpenVrOverlayData> {
};
log::debug!("{}: show", self.state.name);
if let Err(e) = overlay.set_visibility(handle, true) {
panic!("Failed to show overlay: {}", e);
log::error!("{}: Failed to show overlay: {}", self.state.name, e);
}
self.data.visible = true;
self.backend.resume(app);
@@ -104,7 +104,7 @@ impl OverlayData<OpenVrOverlayData> {
};
log::debug!("{}: hide", self.state.name);
if let Err(e) = overlay.set_visibility(handle, false) {
panic!("Failed to hide overlay: {}", e);
log::error!("{}: Failed to hide overlay: {}", self.state.name, e);
}
self.data.visible = false;
self.backend.pause(app);
@@ -116,7 +116,7 @@ impl OverlayData<OpenVrOverlayData> {
return;
};
if let Err(e) = overlay.set_opacity(handle, self.state.alpha) {
panic!("Failed to set overlay alpha: {}", e);
log::error!("{}: Failed to set overlay alpha: {}", self.state.name, e);
}
}
@@ -134,7 +134,7 @@ impl OverlayData<OpenVrOverlayData> {
a: self.data.color.w,
},
) {
panic!("Failed to set overlay tint: {}", e);
log::error!("{}: Failed to set overlay tint: {}", self.state.name, e);
}
}
@@ -144,7 +144,7 @@ impl OverlayData<OpenVrOverlayData> {
return;
};
if let Err(e) = overlay.set_width(handle, self.data.width) {
panic!("Failed to set overlay width: {}", e);
log::error!("{}: Failed to set overlay width: {}", self.state.name, e);
}
}
@@ -154,7 +154,11 @@ impl OverlayData<OpenVrOverlayData> {
return;
};
if let Err(e) = overlay.set_curvature(handle, self.data.curvature) {
panic!("Failed to set overlay curvature: {}", e);
log::error!(
"{}: Failed to set overlay curvature: {}",
self.state.name,
e
);
}
}
@@ -164,7 +168,7 @@ impl OverlayData<OpenVrOverlayData> {
return;
};
if let Err(e) = overlay.set_sort_order(handle, self.data.sort_order) {
panic!("Failed to set overlay z order: {}", e);
log::error!("{}: Failed to set overlay z order: {}", self.state.name, e);
}
}
@@ -181,7 +185,11 @@ impl OverlayData<OpenVrOverlayData> {
ETrackingUniverseOrigin::TrackingUniverseStanding,
&transform,
) {
panic!("Failed to set overlay transform: {}", e);
log::error!(
"{}: Failed to set overlay transform: {}",
self.state.name,
e
);
}
}
@@ -230,8 +238,7 @@ impl OverlayData<OpenVrOverlayData> {
image.usage()
);
if let Err(e) = overlay.set_image_vulkan(handle, &mut texture) {
panic!("Failed to set overlay texture: {}", e);
log::error!("{}: Failed to set overlay texture: {}", self.state.name, e);
}
log::debug!("{}: Uploaded texture", self.state.name);
}
}

View File

@@ -57,27 +57,26 @@ pub(super) struct OpenXrHandSource {
}
impl OpenXrInputSource {
pub fn new(xr: &XrState) -> Self {
let mut action_set = xr
.session
.instance()
.create_action_set("wlx-overlay-s", "WlxOverlay-S Actions", 0)
.expect("Failed to create action set");
pub fn new(xr: &XrState) -> Result<Self, xr::sys::Result> {
let mut action_set =
xr.session
.instance()
.create_action_set("wlx-overlay-s", "WlxOverlay-S Actions", 0)?;
let left_source = OpenXrHandSource::new(&mut action_set, "left");
let right_source = OpenXrHandSource::new(&mut action_set, "right");
let left_source = OpenXrHandSource::new(&mut action_set, "left")?;
let right_source = OpenXrHandSource::new(&mut action_set, "right")?;
suggest_bindings(&xr.instance, &[&left_source, &right_source]);
suggest_bindings(&xr.instance, &[&left_source, &right_source])?;
xr.session.attach_action_sets(&[&action_set]).unwrap();
xr.session.attach_action_sets(&[&action_set])?;
Self {
Ok(Self {
action_set,
hands: [
OpenXrHand::new(&xr, left_source),
OpenXrHand::new(&xr, right_source),
OpenXrHand::new(&xr, left_source)?,
OpenXrHand::new(&xr, right_source)?,
],
}
})
}
pub fn haptics(&self, xr: &XrState, hand: usize, haptics: &Haptics) {
@@ -95,10 +94,8 @@ impl OpenXrInputSource {
);
}
pub fn update(&self, xr: &XrState, state: &mut AppState) {
xr.session
.sync_actions(&[(&self.action_set).into()])
.unwrap();
pub fn update(&self, xr: &XrState, state: &mut AppState) -> Result<(), xr::sys::Result> {
xr.session.sync_actions(&[(&self.action_set).into()])?;
for i in 0..2 {
self.hands[i].update(
@@ -106,19 +103,21 @@ impl OpenXrInputSource {
&xr.stage,
&xr.session,
xr.predicted_display_time,
);
)?;
}
Ok(())
}
}
impl OpenXrHand {
pub(super) fn new(xr: &XrState, source: OpenXrHandSource) -> Self {
let space = source
.action_pose
.create_space(xr.session.clone(), xr::Path::NULL, xr::Posef::IDENTITY)
.unwrap();
pub(super) fn new(xr: &XrState, source: OpenXrHandSource) -> Result<Self, xr::sys::Result> {
let space = source.action_pose.create_space(
xr.session.clone(),
xr::Path::NULL,
xr::Posef::IDENTITY,
)?;
Self { source, space }
Ok(Self { source, space })
}
pub(super) fn update(
@@ -127,8 +126,8 @@ impl OpenXrHand {
stage: &xr::Space,
session: &XrSession,
time: xr::Time,
) {
let location = self.space.locate(stage, time).unwrap();
) -> Result<(), xr::sys::Result> {
let location = self.space.locate(stage, time)?;
if location
.location_flags
.contains(xr::SpaceLocationFlags::ORIENTATION_VALID)
@@ -141,126 +140,103 @@ impl OpenXrHand {
pointer.now.click = self
.source
.action_click
.state(session, xr::Path::NULL)
.unwrap()
.state(session, xr::Path::NULL)?
.current_state
> 0.7;
pointer.now.grab = self
.source
.action_grab
.state(session, xr::Path::NULL)
.unwrap()
.state(session, xr::Path::NULL)?
.current_state
> 0.7;
pointer.now.scroll = self
.source
.action_scroll
.state(session, xr::Path::NULL)
.unwrap()
.state(session, xr::Path::NULL)?
.current_state;
pointer.now.alt_click = self
.source
.action_alt_click
.state(session, xr::Path::NULL)
.unwrap()
.state(session, xr::Path::NULL)?
.current_state
> 0.7;
pointer.now.show_hide = self
.source
.action_show_hide
.state(session, xr::Path::NULL)
.unwrap()
.state(session, xr::Path::NULL)?
.current_state;
pointer.now.click_modifier_right = self
.source
.action_click_modifier_right
.state(session, xr::Path::NULL)
.unwrap()
.state(session, xr::Path::NULL)?
.current_state;
pointer.now.click_modifier_middle = self
.source
.action_click_modifier_middle
.state(session, xr::Path::NULL)
.unwrap()
.state(session, xr::Path::NULL)?
.current_state;
Ok(())
}
}
// supported action types: Haptic, Posef, Vector2f, f32, bool
impl OpenXrHandSource {
pub(super) fn new(action_set: &mut xr::ActionSet, side: &str) -> Self {
let action_pose = action_set
.create_action::<xr::Posef>(
&format!("{}_hand", side),
&format!("{} hand pose", side),
&[],
)
.unwrap();
pub(super) fn new(action_set: &mut xr::ActionSet, side: &str) -> Result<Self, xr::sys::Result> {
let action_pose = action_set.create_action::<xr::Posef>(
&format!("{}_hand", side),
&format!("{} hand pose", side),
&[],
)?;
let action_click = action_set
.create_action::<f32>(
&format!("{}_click", side),
&format!("{} hand click", side),
&[],
)
.unwrap();
let action_grab = action_set
.create_action::<f32>(
&format!("{}_grab", side),
&format!("{} hand grab", side),
&[],
)
.unwrap();
let action_scroll = action_set
.create_action::<f32>(
&format!("{}_scroll", side),
&format!("{} hand scroll", side),
&[],
)
.unwrap();
let action_alt_click = action_set
.create_action::<f32>(
&format!("{}_alt_click", side),
&format!("{} hand alt click", side),
&[],
)
.unwrap();
let action_show_hide = action_set
.create_action::<bool>(
&format!("{}_show_hide", side),
&format!("{} hand show/hide", side),
&[],
)
.unwrap();
let action_click_modifier_right = action_set
.create_action::<bool>(
&format!("{}_click_modifier_right", side),
&format!("{} hand right click modifier", side),
&[],
)
.unwrap();
let action_click_modifier_middle = action_set
.create_action::<bool>(
&format!("{}_click_modifier_middle", side),
&format!("{} hand middle click modifier", side),
&[],
)
.unwrap();
let action_haptics = action_set
.create_action::<xr::Haptic>(
&format!("{}_haptics", side),
&format!("{} hand haptics", side),
&[],
)
.unwrap();
let action_click = action_set.create_action::<f32>(
&format!("{}_click", side),
&format!("{} hand click", side),
&[],
)?;
let action_grab = action_set.create_action::<f32>(
&format!("{}_grab", side),
&format!("{} hand grab", side),
&[],
)?;
let action_scroll = action_set.create_action::<f32>(
&format!("{}_scroll", side),
&format!("{} hand scroll", side),
&[],
)?;
let action_alt_click = action_set.create_action::<f32>(
&format!("{}_alt_click", side),
&format!("{} hand alt click", side),
&[],
)?;
let action_show_hide = action_set.create_action::<bool>(
&format!("{}_show_hide", side),
&format!("{} hand show/hide", side),
&[],
)?;
let action_click_modifier_right = action_set.create_action::<bool>(
&format!("{}_click_modifier_right", side),
&format!("{} hand right click modifier", side),
&[],
)?;
let action_click_modifier_middle = action_set.create_action::<bool>(
&format!("{}_click_modifier_middle", side),
&format!("{} hand middle click modifier", side),
&[],
)?;
let action_haptics = action_set.create_action::<xr::Haptic>(
&format!("{}_haptics", side),
&format!("{} hand haptics", side),
&[],
)?;
Self {
Ok(Self {
action_pose,
action_click,
action_grab,
@@ -270,354 +246,239 @@ impl OpenXrHandSource {
action_click_modifier_right,
action_click_modifier_middle,
action_haptics,
}
})
}
}
fn suggest_bindings(instance: &xr::Instance, hands: &[&OpenXrHandSource; 2]) {
let path = instance
.string_to_path("/interaction_profiles/khr/simple_controller")
.unwrap();
fn suggest_bindings(
instance: &xr::Instance,
hands: &[&OpenXrHandSource; 2],
) -> Result<(), xr::sys::Result> {
let path = instance.string_to_path("/interaction_profiles/khr/simple_controller")?;
// not fully functional, but helpful for debugging
instance
.suggest_interaction_profile_bindings(
path,
&[
xr::Binding::new(
&hands[0].action_pose,
instance
.string_to_path("/user/hand/left/input/aim/pose")
.unwrap(),
),
xr::Binding::new(
&hands[1].action_pose,
instance
.string_to_path("/user/hand/right/input/aim/pose")
.unwrap(),
),
xr::Binding::new(
&hands[0].action_click,
instance
.string_to_path("/user/hand/left/input/select/click")
.unwrap(),
),
xr::Binding::new(
&hands[1].action_click,
instance
.string_to_path("/user/hand/right/input/select/click")
.unwrap(),
),
xr::Binding::new(
&hands[0].action_show_hide,
instance
.string_to_path("/user/hand/left/input/menu/click")
.unwrap(),
),
xr::Binding::new(
&hands[0].action_haptics,
instance
.string_to_path("/user/hand/left/output/haptic")
.unwrap(),
),
xr::Binding::new(
&hands[1].action_haptics,
instance
.string_to_path("/user/hand/right/output/haptic")
.unwrap(),
),
],
)
.unwrap();
instance.suggest_interaction_profile_bindings(
path,
&[
xr::Binding::new(
&hands[0].action_pose,
instance.string_to_path("/user/hand/left/input/aim/pose")?,
),
xr::Binding::new(
&hands[1].action_pose,
instance.string_to_path("/user/hand/right/input/aim/pose")?,
),
xr::Binding::new(
&hands[0].action_click,
instance.string_to_path("/user/hand/left/input/select/click")?,
),
xr::Binding::new(
&hands[1].action_click,
instance.string_to_path("/user/hand/right/input/select/click")?,
),
xr::Binding::new(
&hands[0].action_show_hide,
instance.string_to_path("/user/hand/left/input/menu/click")?,
),
xr::Binding::new(
&hands[0].action_haptics,
instance.string_to_path("/user/hand/left/output/haptic")?,
),
xr::Binding::new(
&hands[1].action_haptics,
instance.string_to_path("/user/hand/right/output/haptic")?,
),
],
)?;
let path = instance
.string_to_path("/interaction_profiles/oculus/touch_controller")
.unwrap();
instance
.suggest_interaction_profile_bindings(
path,
&[
xr::Binding::new(
&hands[0].action_pose,
instance
.string_to_path("/user/hand/left/input/aim/pose")
.unwrap(),
),
xr::Binding::new(
&hands[1].action_pose,
instance
.string_to_path("/user/hand/right/input/aim/pose")
.unwrap(),
),
xr::Binding::new(
&hands[0].action_click,
instance
.string_to_path("/user/hand/left/input/trigger/value")
.unwrap(),
),
xr::Binding::new(
&hands[1].action_click,
instance
.string_to_path("/user/hand/right/input/trigger/value")
.unwrap(),
),
xr::Binding::new(
&hands[0].action_grab,
instance
.string_to_path("/user/hand/left/input/squeeze/value")
.unwrap(),
),
xr::Binding::new(
&hands[1].action_grab,
instance
.string_to_path("/user/hand/right/input/squeeze/value")
.unwrap(),
),
xr::Binding::new(
&hands[0].action_scroll,
instance
.string_to_path("/user/hand/left/input/thumbstick/y")
.unwrap(),
),
xr::Binding::new(
&hands[1].action_scroll,
instance
.string_to_path("/user/hand/right/input/thumbstick/y")
.unwrap(),
),
xr::Binding::new(
&hands[0].action_show_hide,
instance
.string_to_path("/user/hand/left/input/y/click")
.unwrap(),
),
xr::Binding::new(
&hands[0].action_click_modifier_right,
instance
.string_to_path("/user/hand/left/input/y/touch")
.unwrap(),
),
xr::Binding::new(
&hands[1].action_click_modifier_right,
instance
.string_to_path("/user/hand/right/input/b/touch")
.unwrap(),
),
xr::Binding::new(
&hands[0].action_click_modifier_middle,
instance
.string_to_path("/user/hand/left/input/x/touch")
.unwrap(),
),
xr::Binding::new(
&hands[1].action_click_modifier_middle,
instance
.string_to_path("/user/hand/right/input/a/touch")
.unwrap(),
),
xr::Binding::new(
&hands[0].action_haptics,
instance
.string_to_path("/user/hand/left/output/haptic")
.unwrap(),
),
xr::Binding::new(
&hands[1].action_haptics,
instance
.string_to_path("/user/hand/right/output/haptic")
.unwrap(),
),
],
)
.unwrap();
let path = instance.string_to_path("/interaction_profiles/oculus/touch_controller")?;
instance.suggest_interaction_profile_bindings(
path,
&[
xr::Binding::new(
&hands[0].action_pose,
instance.string_to_path("/user/hand/left/input/aim/pose")?,
),
xr::Binding::new(
&hands[1].action_pose,
instance.string_to_path("/user/hand/right/input/aim/pose")?,
),
xr::Binding::new(
&hands[0].action_click,
instance.string_to_path("/user/hand/left/input/trigger/value")?,
),
xr::Binding::new(
&hands[1].action_click,
instance.string_to_path("/user/hand/right/input/trigger/value")?,
),
xr::Binding::new(
&hands[0].action_grab,
instance.string_to_path("/user/hand/left/input/squeeze/value")?,
),
xr::Binding::new(
&hands[1].action_grab,
instance.string_to_path("/user/hand/right/input/squeeze/value")?,
),
xr::Binding::new(
&hands[0].action_scroll,
instance.string_to_path("/user/hand/left/input/thumbstick/y")?,
),
xr::Binding::new(
&hands[1].action_scroll,
instance.string_to_path("/user/hand/right/input/thumbstick/y")?,
),
xr::Binding::new(
&hands[0].action_show_hide,
instance.string_to_path("/user/hand/left/input/y/click")?,
),
xr::Binding::new(
&hands[0].action_click_modifier_right,
instance.string_to_path("/user/hand/left/input/y/touch")?,
),
xr::Binding::new(
&hands[1].action_click_modifier_right,
instance.string_to_path("/user/hand/right/input/b/touch")?,
),
xr::Binding::new(
&hands[0].action_click_modifier_middle,
instance.string_to_path("/user/hand/left/input/x/touch")?,
),
xr::Binding::new(
&hands[1].action_click_modifier_middle,
instance.string_to_path("/user/hand/right/input/a/touch")?,
),
xr::Binding::new(
&hands[0].action_haptics,
instance.string_to_path("/user/hand/left/output/haptic")?,
),
xr::Binding::new(
&hands[1].action_haptics,
instance.string_to_path("/user/hand/right/output/haptic")?,
),
],
)?;
let path = instance
.string_to_path("/interaction_profiles/valve/index_controller")
.unwrap();
instance
.suggest_interaction_profile_bindings(
path,
&[
xr::Binding::new(
&hands[0].action_pose,
instance
.string_to_path("/user/hand/left/input/aim/pose")
.unwrap(),
),
xr::Binding::new(
&hands[1].action_pose,
instance
.string_to_path("/user/hand/right/input/aim/pose")
.unwrap(),
),
xr::Binding::new(
&hands[0].action_click,
instance
.string_to_path("/user/hand/left/input/trigger/value")
.unwrap(),
),
xr::Binding::new(
&hands[1].action_click,
instance
.string_to_path("/user/hand/right/input/trigger/value")
.unwrap(),
),
xr::Binding::new(
&hands[0].action_grab,
instance
.string_to_path("/user/hand/left/input/squeeze/value")
.unwrap(),
),
xr::Binding::new(
&hands[1].action_grab,
instance
.string_to_path("/user/hand/right/input/squeeze/value")
.unwrap(),
),
xr::Binding::new(
&hands[0].action_scroll,
instance
.string_to_path("/user/hand/left/input/thumbstick/y")
.unwrap(),
),
xr::Binding::new(
&hands[1].action_scroll,
instance
.string_to_path("/user/hand/right/input/thumbstick/y")
.unwrap(),
),
xr::Binding::new(
&hands[0].action_alt_click,
instance
.string_to_path("/user/hand/left/input/trackpad/force")
.unwrap(),
),
xr::Binding::new(
&hands[1].action_alt_click,
instance
.string_to_path("/user/hand/right/input/trackpad/force")
.unwrap(),
),
xr::Binding::new(
&hands[0].action_show_hide,
instance
.string_to_path("/user/hand/left/input/b/click")
.unwrap(),
),
xr::Binding::new(
&hands[0].action_click_modifier_right,
instance
.string_to_path("/user/hand/left/input/b/touch")
.unwrap(),
),
xr::Binding::new(
&hands[1].action_click_modifier_right,
instance
.string_to_path("/user/hand/right/input/b/touch")
.unwrap(),
),
xr::Binding::new(
&hands[0].action_click_modifier_middle,
instance
.string_to_path("/user/hand/left/input/a/touch")
.unwrap(),
),
xr::Binding::new(
&hands[1].action_click_modifier_middle,
instance
.string_to_path("/user/hand/right/input/a/touch")
.unwrap(),
),
xr::Binding::new(
&hands[0].action_haptics,
instance
.string_to_path("/user/hand/left/output/haptic")
.unwrap(),
),
xr::Binding::new(
&hands[1].action_haptics,
instance
.string_to_path("/user/hand/right/output/haptic")
.unwrap(),
),
],
)
.unwrap();
let path = instance.string_to_path("/interaction_profiles/valve/index_controller")?;
instance.suggest_interaction_profile_bindings(
path,
&[
xr::Binding::new(
&hands[0].action_pose,
instance.string_to_path("/user/hand/left/input/aim/pose")?,
),
xr::Binding::new(
&hands[1].action_pose,
instance.string_to_path("/user/hand/right/input/aim/pose")?,
),
xr::Binding::new(
&hands[0].action_click,
instance.string_to_path("/user/hand/left/input/trigger/value")?,
),
xr::Binding::new(
&hands[1].action_click,
instance.string_to_path("/user/hand/right/input/trigger/value")?,
),
xr::Binding::new(
&hands[0].action_grab,
instance.string_to_path("/user/hand/left/input/squeeze/value")?,
),
xr::Binding::new(
&hands[1].action_grab,
instance.string_to_path("/user/hand/right/input/squeeze/value")?,
),
xr::Binding::new(
&hands[0].action_scroll,
instance.string_to_path("/user/hand/left/input/thumbstick/y")?,
),
xr::Binding::new(
&hands[1].action_scroll,
instance.string_to_path("/user/hand/right/input/thumbstick/y")?,
),
xr::Binding::new(
&hands[0].action_alt_click,
instance.string_to_path("/user/hand/left/input/trackpad/force")?,
),
xr::Binding::new(
&hands[1].action_alt_click,
instance.string_to_path("/user/hand/right/input/trackpad/force")?,
),
xr::Binding::new(
&hands[0].action_show_hide,
instance.string_to_path("/user/hand/left/input/b/click")?,
),
xr::Binding::new(
&hands[0].action_click_modifier_right,
instance.string_to_path("/user/hand/left/input/b/touch")?,
),
xr::Binding::new(
&hands[1].action_click_modifier_right,
instance.string_to_path("/user/hand/right/input/b/touch")?,
),
xr::Binding::new(
&hands[0].action_click_modifier_middle,
instance.string_to_path("/user/hand/left/input/a/touch")?,
),
xr::Binding::new(
&hands[1].action_click_modifier_middle,
instance.string_to_path("/user/hand/right/input/a/touch")?,
),
xr::Binding::new(
&hands[0].action_haptics,
instance.string_to_path("/user/hand/left/output/haptic")?,
),
xr::Binding::new(
&hands[1].action_haptics,
instance.string_to_path("/user/hand/right/output/haptic")?,
),
],
)?;
let path = instance
.string_to_path("/interaction_profiles/htc/vive_controller")
.unwrap();
instance
.suggest_interaction_profile_bindings(
path,
&[
xr::Binding::new(
&hands[0].action_pose,
instance
.string_to_path("/user/hand/left/input/aim/pose")
.unwrap(),
),
xr::Binding::new(
&hands[1].action_pose,
instance
.string_to_path("/user/hand/right/input/aim/pose")
.unwrap(),
),
xr::Binding::new(
&hands[0].action_click,
instance
.string_to_path("/user/hand/left/input/trigger/value")
.unwrap(),
),
xr::Binding::new(
&hands[1].action_click,
instance
.string_to_path("/user/hand/right/input/trigger/value")
.unwrap(),
),
xr::Binding::new(
&hands[0].action_grab,
instance
.string_to_path("/user/hand/left/input/squeeze/click")
.unwrap(),
),
xr::Binding::new(
&hands[1].action_grab,
instance
.string_to_path("/user/hand/right/input/squeeze/click")
.unwrap(),
),
xr::Binding::new(
&hands[0].action_scroll,
instance
.string_to_path("/user/hand/left/input/trackpad/y")
.unwrap(),
),
xr::Binding::new(
&hands[1].action_scroll,
instance
.string_to_path("/user/hand/right/input/trackpad/y")
.unwrap(),
),
xr::Binding::new(
&hands[0].action_show_hide,
instance
.string_to_path("/user/hand/left/input/menu/click")
.unwrap(),
),
xr::Binding::new(
&hands[0].action_haptics,
instance
.string_to_path("/user/hand/left/output/haptic")
.unwrap(),
),
xr::Binding::new(
&hands[1].action_haptics,
instance
.string_to_path("/user/hand/right/output/haptic")
.unwrap(),
),
],
)
.unwrap();
let path = instance.string_to_path("/interaction_profiles/htc/vive_controller")?;
instance.suggest_interaction_profile_bindings(
path,
&[
xr::Binding::new(
&hands[0].action_pose,
instance.string_to_path("/user/hand/left/input/aim/pose")?,
),
xr::Binding::new(
&hands[1].action_pose,
instance.string_to_path("/user/hand/right/input/aim/pose")?,
),
xr::Binding::new(
&hands[1].action_click,
instance.string_to_path("/user/hand/right/input/trigger/value")?,
),
xr::Binding::new(
&hands[0].action_grab,
instance.string_to_path("/user/hand/left/input/squeeze/click")?,
),
xr::Binding::new(
&hands[1].action_grab,
instance.string_to_path("/user/hand/right/input/squeeze/click")?,
),
xr::Binding::new(
&hands[0].action_scroll,
instance.string_to_path("/user/hand/left/input/trackpad/y")?,
),
xr::Binding::new(
&hands[1].action_scroll,
instance.string_to_path("/user/hand/right/input/trackpad/y")?,
),
xr::Binding::new(
&hands[0].action_show_hide,
instance.string_to_path("/user/hand/left/input/menu/click")?,
),
xr::Binding::new(
&hands[0].action_haptics,
instance.string_to_path("/user/hand/left/output/haptic")?,
),
xr::Binding::new(
&hands[1].action_haptics,
instance.string_to_path("/user/hand/right/output/haptic")?,
),
],
)?;
Ok(())
}

View File

@@ -57,7 +57,7 @@ pub fn openxr_run(running: Arc<AtomicBool>) -> Result<(), BackendError> {
let mut app_state = {
let graphics = WlxGraphics::new_openxr(xr_instance.clone(), system);
AppState::from_graphics(graphics)
AppState::from_graphics(graphics)?
};
let mut overlays = OverlayContainer::<OpenXrOverlayData>::new(&mut app_state);
@@ -109,7 +109,7 @@ pub fn openxr_run(running: Arc<AtomicBool>) -> Result<(), BackendError> {
let watch_id = overlays.get_by_name(WATCH_NAME).unwrap().state.id;
let input_source = input::OpenXrInputSource::new(&xr_state);
let input_source = input::OpenXrInputSource::new(&xr_state)?;
let mut session_running = false;
let mut event_storage = xr::EventDataBuffer::new();
@@ -136,7 +136,7 @@ pub fn openxr_run(running: Arc<AtomicBool>) -> Result<(), BackendError> {
SessionStateChanged(e) => {
// Session state change is where we can begin and end sessions, as well as
// find quit messages!
println!("entered state {:?}", e.state());
log::info!("entered state {:?}", e.state());
match e.state() {
xr::SessionState::READY => {
xr_state.session.begin(VIEW_TYPE).unwrap();
@@ -156,7 +156,7 @@ pub fn openxr_run(running: Arc<AtomicBool>) -> Result<(), BackendError> {
break 'main_loop;
}
EventsLost(e) => {
println!("lost {} events", e.lost_event_count());
log::warn!("lost {} events", e.lost_event_count());
}
_ => {}
}
@@ -200,7 +200,7 @@ pub fn openxr_run(running: Arc<AtomicBool>) -> Result<(), BackendError> {
}
app_state.input_state.pre_update();
input_source.update(&xr_state, &mut app_state);
input_source.update(&xr_state, &mut app_state)?;
app_state.input_state.post_update();
if app_state

View File

@@ -135,7 +135,7 @@ pub fn load_general() -> GeneralConfig {
continue;
}
println!("Loading config file {}", path.path().to_string_lossy());
log::info!("Loading config file {}", path.path().to_string_lossy());
if let Ok(data) = std::fs::read_to_string(path.path()) {
yaml_data.push('\n'); // Just in case, if end of the config file was not newline

View File

@@ -45,7 +45,7 @@ fn get_config_file_path(filename: &str) -> PathBuf {
pub fn load(filename: &str) -> Option<String> {
let path = get_config_file_path(filename);
println!("Loading config {}", path.to_string_lossy());
log::info!("Loading config {}", path.to_string_lossy());
if let Ok(data) = fs::read_to_string(path) {
Some(data)
@@ -60,7 +60,7 @@ macro_rules! load_with_fallback {
if let Some(data) = config_io::load($filename) {
data
} else {
println!(
log::info!(
"Config {}/{} does not exist, using internal fallback",
config_io::CONFIG_ROOT_PATH.to_string_lossy(),
$filename

View File

@@ -184,8 +184,9 @@ impl HidProvider for UInputProvider {
for i in 0..7 {
let m = 1 << i;
if changed & m != 0 {
let vk = MODS_TO_KEYS.get(m).unwrap()[0] as u16;
self.send_key(vk, modifiers & m != 0);
if let Some(vk) = MODS_TO_KEYS.get(m).into_iter().flatten().next() {
self.send_key(*vk as u16, modifiers & m != 0);
}
}
}
self.cur_modifiers = modifiers;

View File

@@ -9,15 +9,25 @@ mod overlays;
mod shaders;
mod state;
use std::sync::{
atomic::{AtomicBool, Ordering},
Arc,
use std::{
io::{stdout, IsTerminal},
sync::{
atomic::{AtomicBool, Ordering},
Arc,
},
};
use env_logger::Env;
use flexi_logger::FileSpec;
fn main() -> Result<(), Box<dyn std::error::Error>> {
if stdout().is_terminal() {
flexi_logger::Logger::try_with_env_or_str("info")?.start()?;
} else {
flexi_logger::Logger::try_with_env_or_str("info")?
.log_to_file(FileSpec::default().directory("/tmp"))
.start()?;
}
fn main() {
env_logger::Builder::from_env(Env::default().default_filter_or("info")).init();
log::info!(
"Welcome to {} version {}!",
env!("CARGO_PKG_NAME"),
@@ -27,7 +37,7 @@ fn main() {
#[cfg(feature = "openvr")]
if std::env::args().any(|arg| arg == "--uninstall") {
crate::backend::openvr::openvr_uninstall();
return;
return Ok(());
}
let running = Arc::new(AtomicBool::new(true));
@@ -38,33 +48,30 @@ fn main() {
}
});
#[cfg(all(feature = "openxr", feature = "openvr"))]
auto_run(running);
// TODO: Handle error messages if using cherry-picked features
#[cfg(all(feature = "openvr", not(feature = "openxr")))]
let _ = crate::backend::openvr::openvr_run(running);
#[cfg(all(feature = "openxr", not(feature = "openvr")))]
let _ = crate::backend::openxr::openxr_run(running);
#[cfg(not(any(feature = "openxr", feature = "openvr")))]
compile_error!("You must enable at least one backend feature (openxr or openvr)");
Ok(())
}
#[cfg(all(feature = "openxr", feature = "openvr"))]
fn auto_run(running: Arc<AtomicBool>) {
use crate::backend::openvr::openvr_run;
use crate::backend::openxr::openxr_run;
use backend::common::BackendError;
let Err(BackendError::NotSupported) = openxr_run(running.clone()) else {
return;
};
#[cfg(feature = "openxr")]
{
use crate::backend::openxr::openxr_run;
let Err(BackendError::NotSupported) = openxr_run(running.clone()) else {
return;
};
}
let Err(BackendError::NotSupported) = openvr_run(running) else {
return;
};
#[cfg(feature = "openxr")]
{
use crate::backend::openvr::openvr_run;
let Err(BackendError::NotSupported) = openvr_run(running) else {
return;
};
}
log::error!("No supported backends found");
}

View File

@@ -87,7 +87,10 @@ where
});
} else if let Some(exec_args) = LAYOUT.exec_commands.get(key) {
maybe_state = Some(KeyButtonData::Exec {
program: exec_args.first().unwrap().clone(),
program: exec_args
.first()
.expect("Keyboard: Invalid EXEC args")
.clone(),
args: exec_args.iter().skip(1).cloned().collect(),
});
} else {

View File

@@ -481,9 +481,10 @@ where
let token = pw_token_store.get(display_name).map(|s| s.as_str());
if let Some(t) = token {
println!(
log::info!(
"Found existing Pipewire token for display {}: {}",
display_name, t
display_name,
t
);
}
@@ -495,7 +496,7 @@ where
.insert(String::from(display_name), token.clone())
.is_none()
{
println!("Adding Pipewire token {}", token);
log::info!("Adding Pipewire token {}", token);
}
}
}

View File

@@ -1,5 +1,6 @@
use std::{path::PathBuf, sync::Arc};
use anyhow::bail;
use glam::{Quat, Vec3};
use vulkano::format::Format;
@@ -27,30 +28,30 @@ pub struct AppState {
}
impl AppState {
pub fn from_graphics(graphics: Arc<WlxGraphics>) -> Self {
pub fn from_graphics(graphics: Arc<WlxGraphics>) -> anyhow::Result<Self> {
// insert shared resources
{
let Ok(mut shaders) = graphics.shared_shaders.write() else {
panic!("Shared Shaders RwLock poisoned");
bail!("Failed to lock shared shaders");
};
let shader = vert_common::load(graphics.device.clone()).unwrap();
let shader = vert_common::load(graphics.device.clone())?;
shaders.insert("vert_common", shader);
let shader = frag_color::load(graphics.device.clone()).unwrap();
let shader = frag_color::load(graphics.device.clone())?;
shaders.insert("frag_color", shader);
let shader = frag_glyph::load(graphics.device.clone()).unwrap();
let shader = frag_glyph::load(graphics.device.clone())?;
shaders.insert("frag_glyph", shader);
let shader = frag_sprite::load(graphics.device.clone()).unwrap();
let shader = frag_sprite::load(graphics.device.clone())?;
shaders.insert("frag_sprite", shader);
let shader = frag_srgb::load(graphics.device.clone()).unwrap();
let shader = frag_srgb::load(graphics.device.clone())?;
shaders.insert("frag_srgb", shader);
}
AppState {
Ok(AppState {
fc: FontCache::new(),
session: AppSession::load(),
tasks: TaskContainer::new(),
@@ -58,7 +59,7 @@ impl AppState {
format: Format::R8G8B8A8_UNORM,
input_state: InputState::new(),
hid_provider: crate::hid::initialize(),
}
})
}
}
@@ -81,7 +82,7 @@ pub struct AppSession {
impl AppSession {
pub fn load() -> Self {
let config_root_path = config_io::ensure_config_root();
println!("Config root path: {}", config_root_path.to_string_lossy());
log::info!("Config root path: {}", config_root_path.to_string_lossy());
let config = GeneralConfig::load_from_disk();
AppSession {