improve error handling
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(())
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(())
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
57
src/main.rs
57
src/main.rs
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
21
src/state.rs
21
src/state.rs
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user