use serde::{Deserialize, Serialize}; use crate::config_io; const DEFAULT_XR_INPUT_PROFILES: &str = include_str!("../assets/openxr_actions.json5"); #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] pub enum OneOrMany { One(T), Many(Vec), } #[derive(Debug, Default, Clone, Serialize, Deserialize)] pub struct OpenXrInputAction { #[serde(skip_serializing_if = "Option::is_none")] pub left: Option>, #[serde(skip_serializing_if = "Option::is_none")] pub right: Option>, #[serde(skip_serializing_if = "Option::is_none")] pub handsfree: Option>, #[serde(skip_serializing_if = "Option::is_none")] pub threshold_left: Option<[f32; 2]>, #[serde(skip_serializing_if = "Option::is_none")] pub threshold_right: Option<[f32; 2]>, #[serde(skip_serializing_if = "Option::is_none")] pub double_click: Option, #[serde(skip_serializing_if = "Option::is_none")] pub triple_click: Option, } #[derive(Debug, Default, Clone, Serialize, Deserialize)] pub struct OpenXrInputProfile { pub profile: String, #[serde(skip_serializing_if = "Option::is_none")] pub pose: Option, #[serde(skip_serializing_if = "Option::is_none")] pub click: Option, #[serde(skip_serializing_if = "Option::is_none")] pub grab: Option, #[serde(skip_serializing_if = "Option::is_none")] pub alt_click: Option, #[serde(skip_serializing_if = "Option::is_none")] pub show_hide: Option, #[serde(skip_serializing_if = "Option::is_none")] pub toggle_dashboard: Option, #[serde(skip_serializing_if = "Option::is_none")] pub space_drag: Option, #[serde(skip_serializing_if = "Option::is_none")] pub space_rotate: Option, #[serde(skip_serializing_if = "Option::is_none")] pub space_reset: Option, #[serde(skip_serializing_if = "Option::is_none")] pub click_modifier_right: Option, #[serde(skip_serializing_if = "Option::is_none")] pub click_modifier_middle: Option, #[serde(skip_serializing_if = "Option::is_none")] pub move_mouse: Option, #[serde(skip_serializing_if = "Option::is_none")] pub scroll: Option, #[serde(skip_serializing_if = "Option::is_none")] pub haptic: Option, } pub fn load_xr_input_profiles() -> Vec { let mut profiles: Vec = serde_json5::from_str(DEFAULT_XR_INPUT_PROFILES).unwrap(); // want panic let Some(conf) = config_io::load("openxr_actions.json5") else { return profiles; }; match serde_json5::from_str::>(&conf) { Ok(override_profiles) => { for new in override_profiles { if let Some(i) = profiles.iter().position(|old| old.profile == new.profile) { profiles[i] = new; } else { profiles.push(new); } } } Err(e) => { log::error!("Failed to load openxr_actions.json5: {e}"); } } profiles }