From d2740e2a43799640d1ac7f888509ffa9a7eb4844 Mon Sep 17 00:00:00 2001 From: Riccardo Zaglia Date: Wed, 22 Oct 2025 00:34:50 +1000 Subject: [PATCH 1/2] WIP --- alvr/client_core/src/connection.rs | 2 +- alvr/client_openxr/src/interaction.rs | 16 +- alvr/server_core/src/connection.rs | 22 +- alvr/server_core/src/lib.rs | 8 +- alvr/server_core/src/tracking/face.rs | 14 +- alvr/server_core/src/tracking/mod.rs | 22 +- alvr/server_openvr/src/lib.rs | 2 +- alvr/server_openvr/src/props.rs | 36 +- alvr/server_openvr/src/tracking.rs | 6 +- alvr/session/src/lib.rs | 2 +- alvr/session/src/settings.rs | 711 ++++++++++++++------------ 11 files changed, 458 insertions(+), 383 deletions(-) diff --git a/alvr/client_core/src/connection.rs b/alvr/client_core/src/connection.rs index caabbfdfb8..5d36a449be 100644 --- a/alvr/client_core/src/connection.rs +++ b/alvr/client_core/src/connection.rs @@ -195,7 +195,7 @@ fn connection_pipeline( let settings = stream_config.settings; let negotiated_config = stream_config.negotiated_config; - *ctx.max_prediction.write() = Duration::from_millis(settings.headset.max_prediction_ms); + *ctx.max_prediction.write() = Duration::from_millis(settings.inputs.max_prediction_ms); *ctx.statistics_manager.lock() = Some(StatisticsManager::new( settings.connection.statistics_history_size, diff --git a/alvr/client_openxr/src/interaction.rs b/alvr/client_openxr/src/interaction.rs index d3adbf397f..f067bb2a5e 100644 --- a/alvr/client_openxr/src/interaction.rs +++ b/alvr/client_openxr/src/interaction.rs @@ -12,7 +12,7 @@ use alvr_common::{ }; use alvr_graphics::HandData; use alvr_packets::{ButtonEntry, ButtonValue, FaceData, FaceExpressions, StreamConfig}; -use alvr_session::{BodyTrackingBDConfig, BodyTrackingSourcesConfig, FaceTrackingSourcesConfig}; +use alvr_session::{BodyTrackingBDConfig, BodyTrackingSourcesConfig, FaceTrackingConfig}; use openxr as xr; use std::{ collections::{HashMap, HashSet}, @@ -138,7 +138,7 @@ pub enum BodyTracker { #[derive(Clone)] pub struct InteractionSourcesConfig { - pub face_tracking: Option, + pub face_tracking: Option, pub body_tracking: Option, pub prefers_multimodal_input: bool, } @@ -148,19 +148,19 @@ impl InteractionSourcesConfig { Self { face_tracking: config .settings - .headset + .inputs .face_tracking .as_option() .map(|c| c.sources.clone()), body_tracking: config .settings - .headset + .inputs .body_tracking .as_option() .map(|c| c.sources.clone()), prefers_multimodal_input: config .settings - .headset + .inputs .multimodal_tracking .as_option() .is_some_and(|c| c.enabled), @@ -523,7 +523,7 @@ impl InteractionContext { if let Some(config) = &config.face_tracking { if matches!(self.platform, Platform::QuestPro) - && matches!(config, FaceTrackingSourcesConfig::PreferFullFaceTracking) + && matches!(config, FaceTrackingConfig::PreferFullFaceTracking) { #[cfg(target_os = "android")] { @@ -535,7 +535,7 @@ impl InteractionContext { if matches!( self.platform, Platform::PicoNeo3 | Platform::Pico4Pro | Platform::Pico4Enterprise - ) && matches!(config, FaceTrackingSourcesConfig::PreferFullFaceTracking) + ) && matches!(config, FaceTrackingConfig::PreferFullFaceTracking) && extra_extensions::supports_eye_gaze_interaction(&self.xr_session, self.xr_system) { #[cfg(target_os = "android")] @@ -569,7 +569,7 @@ impl InteractionContext { self.face_sources.eyes_social = check_ext_object("EyeTrackerSocial", EyeTrackerSocial::new(&self.xr_session)); - if matches!(config, FaceTrackingSourcesConfig::PreferFullFaceTracking) { + if matches!(config, FaceTrackingConfig::PreferFullFaceTracking) { if let Some(tracker) = check_ext_object( "FaceTracker2FB", FaceTracker2FB::new(self.xr_session.clone(), true, true), diff --git a/alvr/server_core/src/connection.rs b/alvr/server_core/src/connection.rs index ba9ba6ad26..35c1cc77a5 100644 --- a/alvr/server_core/src/connection.rs +++ b/alvr/server_core/src/connection.rs @@ -71,7 +71,7 @@ pub fn contruct_openvr_config(session: &SessionConfig) -> OpenvrConfig { let mut controller_is_tracker = false; let mut controller_profile = 0; let mut use_separate_hand_trackers = false; - let controllers_enabled = if let Switch::Enabled(config) = &settings.headset.controllers { + let controllers_enabled = if let Switch::Enabled(config) = &settings.inputs.controllers { controller_is_tracker = matches!(config.emulation_mode, ControllersEmulationMode::ViveTracker); // These numbers don't mean anything, they're just for triggering SteamVR resets. @@ -101,9 +101,9 @@ pub fn contruct_openvr_config(session: &SessionConfig) -> OpenvrConfig { }; let body_tracking_vive_enabled = - if let Switch::Enabled(config) = &settings.headset.body_tracking { + if let Switch::Enabled(config) = &settings.inputs.body_tracking { matches!(config.sink, BodyTrackingSinkConfig::FakeViveTracker) - } else if let Switch::Enabled(config) = settings.headset.multimodal_tracking { + } else if let Switch::Enabled(config) = settings.inputs.multimodal_tracking { config.detached_controllers_steamvr_sink } else { false @@ -111,7 +111,7 @@ pub fn contruct_openvr_config(session: &SessionConfig) -> OpenvrConfig { // Should be true if using full body tracking let body_tracking_has_legs = settings - .headset + .inputs .body_tracking .as_option() .map(|c| c.sources.meta.prefer_full_body) @@ -158,8 +158,8 @@ pub fn contruct_openvr_config(session: &SessionConfig) -> OpenvrConfig { let hdr_controls = settings.video.encoder_config.hdr; OpenvrConfig { - tracking_ref_only: settings.headset.tracking_ref_only, - enable_vive_tracker_proxy: settings.headset.enable_vive_tracker_proxy, + tracking_ref_only: settings.inputs.tracking_ref_only, + enable_vive_tracker_proxy: settings.inputs.enable_vive_tracker_proxy, minimum_idr_interval_ms: settings.connection.minimum_idr_interval_ms, adapter_index: settings.video.adapter_index, codec: settings.video.preferred_codec as _, @@ -792,7 +792,7 @@ fn connection_pipeline( *ctx.statistics_manager.write() = Some(StatisticsManager::new( initial_settings.connection.statistics_history_size, Duration::from_secs_f32(1.0 / fps), - if let Switch::Enabled(config) = &initial_settings.headset.controllers { + if let Switch::Enabled(config) = &initial_settings.inputs.controllers { config.steamvr_pipeline_frames } else { 0.0 @@ -1125,7 +1125,7 @@ fn connection_pipeline( let controllers_config = session_manager_lock .settings() - .headset + .inputs .controllers .as_option(); let mut controller_button_mapping_manager = controllers_config.map(|config| { @@ -1169,9 +1169,9 @@ fn connection_pipeline( match packet { ClientControlPacket::PlayspaceSync(packet) => { - if !initial_settings.headset.tracking_ref_only { + if !initial_settings.inputs.tracking_ref_only { let session_manager_lock = SESSION_MANAGER.read(); - let config = &session_manager_lock.settings().headset; + let config = &session_manager_lock.settings().inputs; ctx.tracking_manager.write().recenter( config.position_recentering_mode, config.rotation_recentering_mode, @@ -1258,7 +1258,7 @@ fn connection_pipeline( } ClientControlPacket::ActiveInteractionProfile { input_ids, .. } => { controller_button_mapping_manager = if let Switch::Enabled(config) = - &SESSION_MANAGER.read().settings().headset.controllers + &SESSION_MANAGER.read().settings().inputs.controllers { if let Some(mappings) = &config.button_mappings { Some(ButtonMappingManager::new_manual(mappings)) diff --git a/alvr/server_core/src/lib.rs b/alvr/server_core/src/lib.rs index 47d6295332..45c092cfc1 100644 --- a/alvr/server_core/src/lib.rs +++ b/alvr/server_core/src/lib.rs @@ -155,7 +155,7 @@ pub fn settings() -> Settings { pub fn registered_button_set() -> HashSet { let session_manager = SESSION_MANAGER.read(); - if let Switch::Enabled(input_mapping) = &session_manager.settings().headset.controllers { + if let Switch::Enabled(input_mapping) = &session_manager.settings().inputs.controllers { input_mapping::registered_button_set(&input_mapping.emulation_mode) } else { HashSet::new() @@ -193,7 +193,7 @@ impl ServerCoreContext { let stats = StatisticsManager::new( initial_settings.connection.statistics_history_size, Duration::from_secs_f32(1.0 / 90.0), - if let Switch::Enabled(config) = &initial_settings.headset.controllers { + if let Switch::Enabled(config) = &initial_settings.inputs.controllers { config.steamvr_pipeline_frames } else { 0.0 @@ -287,7 +287,7 @@ impl ServerCoreContext { .unwrap_or_default(); let max_prediction = - Duration::from_millis(SESSION_MANAGER.read().settings().headset.max_prediction_ms); + Duration::from_millis(SESSION_MANAGER.read().settings().inputs.max_prediction_ms); if latency > max_prediction { warn!("Latency is too high. Clamping prediction"); @@ -329,7 +329,7 @@ impl ServerCoreContext { session_manager_lock .settings() - .headset + .inputs .controllers .as_option() .and_then(|c| c.haptics.as_option().cloned()) diff --git a/alvr/server_core/src/tracking/face.rs b/alvr/server_core/src/tracking/face.rs index 4a62badd17..ff474e66ca 100644 --- a/alvr/server_core/src/tracking/face.rs +++ b/alvr/server_core/src/tracking/face.rs @@ -1,6 +1,6 @@ use alvr_common::{anyhow::Result, glam::EulerRot}; use alvr_packets::{FaceData, FaceExpressions}; -use alvr_session::FaceTrackingSinkConfig; +use alvr_session::FaceTrackingOscOutputConfig; use rosc::{OscMessage, OscPacket, OscType}; use std::{f32::consts::PI, net::UdpSocket}; @@ -9,16 +9,16 @@ const RAD_TO_DEG: f32 = 180.0 / PI; const VRCFT_PORT: u16 = 0xA1F7; pub struct FaceTrackingSink { - config: FaceTrackingSinkConfig, + config: FaceTrackingOscOutputConfig, socket: UdpSocket, packet_buffer: Vec, } impl FaceTrackingSink { - pub fn new(config: FaceTrackingSinkConfig, local_osc_port: u16) -> Result { + pub fn new(config: FaceTrackingOscOutputConfig, local_osc_port: u16) -> Result { let port = match config { - FaceTrackingSinkConfig::VrchatEyeOsc { port } => port, - FaceTrackingSinkConfig::VrcFaceTracking => VRCFT_PORT, + FaceTrackingOscOutputConfig::VrchatEyes { port } => port, + FaceTrackingOscOutputConfig::VrcFaceTracking => VRCFT_PORT, }; let socket = UdpSocket::bind(format!("127.0.0.1:{local_osc_port}"))?; @@ -53,7 +53,7 @@ impl FaceTrackingSink { pub fn send_tracking(&mut self, face_data: &FaceData) { match self.config { - FaceTrackingSinkConfig::VrchatEyeOsc { .. } => { + FaceTrackingOscOutputConfig::VrchatEyes { .. } => { if let [Some(left), Some(right)] = face_data.eyes_social { let (left_pitch, left_yaw, _) = left.to_euler(EulerRot::XYZ); let (right_pitch, right_yaw, _) = right.to_euler(EulerRot::XYZ); @@ -100,7 +100,7 @@ impl FaceTrackingSink { ); } } - FaceTrackingSinkConfig::VrcFaceTracking => { + FaceTrackingOscOutputConfig::VrcFaceTracking => { self.packet_buffer.clear(); if let [Some(left_quat), Some(right_quat)] = face_data.eyes_social { diff --git a/alvr/server_core/src/tracking/mod.rs b/alvr/server_core/src/tracking/mod.rs index 87ec76d431..24e79546c9 100644 --- a/alvr/server_core/src/tracking/mod.rs +++ b/alvr/server_core/src/tracking/mod.rs @@ -22,7 +22,7 @@ use alvr_common::{ use alvr_events::{EventType, TrackingEvent}; use alvr_packets::TrackingData; use alvr_session::{ - BodyTrackingConfig, HeadsetConfig, PositionRecenteringMode, RotationRecenteringMode, Settings, + BodyTrackingConfig, InputsConfig, PositionRecenteringMode, RotationRecenteringMode, Settings, VMCConfig, settings_schema::Switch, }; use alvr_sockets::StreamReceiver; @@ -120,7 +120,7 @@ impl TrackingManager { // Performs all kinds of tracking transformations, driven by settings. pub fn report_device_motions( &mut self, - headset_config: &HeadsetConfig, + headset_config: &InputsConfig, timestamp: Duration, device_motions: &[(u64, DeviceMotion)], ) { @@ -277,7 +277,7 @@ pub fn tracking_loop( ) { let mut gestures_button_mapping_manager = initial_settings - .headset + .inputs .controllers .as_option() .map(|config| { @@ -289,7 +289,7 @@ pub fn tracking_loop( }); let mut face_tracking_sink = initial_settings - .headset + .inputs .face_tracking .into_option() .and_then(|config| { @@ -297,7 +297,7 @@ pub fn tracking_loop( }); let mut body_tracking_sink = initial_settings - .headset + .inputs .body_tracking .into_option() .and_then(|config| { @@ -305,7 +305,7 @@ pub fn tracking_loop( }); let mut vmc_sink = initial_settings - .headset + .inputs .vmc .into_option() .and_then(|config| VMCSink::new(config).ok()); @@ -330,7 +330,7 @@ pub fn tracking_loop( let data_lock = SESSION_MANAGER.read(); data_lock .settings() - .headset + .inputs .controllers .clone() .into_option() @@ -339,7 +339,7 @@ pub fn tracking_loop( let device_motion_keys = { let mut tracking_manager_lock = ctx.tracking_manager.write(); let session_manager_lock = SESSION_MANAGER.read(); - let headset_config = &session_manager_lock.settings().headset; + let headset_config = &session_manager_lock.settings().inputs; tracking.device_motions.extend_from_slice( &body::get_default_body_trackers_from_detached_controllers( @@ -461,12 +461,12 @@ pub fn tracking_loop( .ok(); let publish_vmc = matches!( - SESSION_MANAGER.read().settings().headset.vmc, + SESSION_MANAGER.read().settings().inputs.vmc, Switch::Enabled(VMCConfig { publish: true, .. }) ); if publish_vmc { let orientation_correction = matches!( - SESSION_MANAGER.read().settings().headset.vmc, + SESSION_MANAGER.read().settings().inputs.vmc, Switch::Enabled(VMCConfig { orientation_correction: true, .. @@ -498,7 +498,7 @@ pub fn tracking_loop( } let track_body = matches!( - SESSION_MANAGER.read().settings().headset.body_tracking, + SESSION_MANAGER.read().settings().inputs.body_tracking, Switch::Enabled(BodyTrackingConfig { tracked: true, .. }) ); if track_body && let Some(sink) = &mut body_tracking_sink { diff --git a/alvr/server_openvr/src/lib.rs b/alvr/server_openvr/src/lib.rs index 3861ca0238..7a5935b050 100644 --- a/alvr/server_openvr/src/lib.rs +++ b/alvr/server_openvr/src/lib.rs @@ -83,7 +83,7 @@ fn event_loop(events_receiver: mpsc::Receiver) { SetLocalViewParams(ffi_params.as_ptr()); }, ServerCoreEvent::Tracking { poll_timestamp } => { - let headset_config = &alvr_server_core::settings().headset; + let headset_config = &alvr_server_core::settings().inputs; let controllers_config = headset_config.controllers.clone().into_option(); let track_body = headset_config.body_tracking.enabled(); diff --git a/alvr/server_openvr/src/props.rs b/alvr/server_openvr/src/props.rs index 6858a8a61c..0bfd9c4376 100644 --- a/alvr/server_openvr/src/props.rs +++ b/alvr/server_openvr/src/props.rs @@ -14,7 +14,7 @@ use alvr_common::{ settings_schema::Switch, warn, }; use alvr_session::{ - ControllersEmulationMode, HeadsetEmulationMode, OpenvrPropKey, OpenvrPropType, OpenvrProperty, + ControllersEmulationMode, HmdEmulationMode, OpenvrPropKey, OpenvrPropType, OpenvrProperty, }; use std::{ ffi::{CString, c_char, c_void}, @@ -119,16 +119,16 @@ fn serial_number(device_id: u64) -> String { let settings = alvr_server_core::settings(); if device_id == *HEAD_ID { - match &settings.headset.emulation_mode { - HeadsetEmulationMode::RiftS => "1WMGH000XX0000".into(), - HeadsetEmulationMode::Quest1 => "1PASH0X0X00000".into(), - HeadsetEmulationMode::Quest2 => "1WMHH000X00000".into(), - HeadsetEmulationMode::QuestPro => "230YC0XXXX00XX".into(), - HeadsetEmulationMode::Vive => "HTCVive-001".into(), - HeadsetEmulationMode::Custom { serial_number, .. } => serial_number.clone(), + match &settings.inputs.emulation_mode { + HmdEmulationMode::RiftS => "1WMGH000XX0000".into(), + HmdEmulationMode::Quest1 => "1PASH0X0X00000".into(), + HmdEmulationMode::Quest2 => "1WMHH000X00000".into(), + HmdEmulationMode::QuestPro => "230YC0XXXX00XX".into(), + HmdEmulationMode::Vive => "HTCVive-001".into(), + HmdEmulationMode::Custom { serial_number, .. } => serial_number.clone(), } } else if device_id == *HAND_LEFT_ID || device_id == *HAND_RIGHT_ID { - if let Switch::Enabled(controllers) = &settings.headset.controllers { + if let Switch::Enabled(controllers) = &settings.inputs.controllers { let serial_number = match &controllers.emulation_mode { ControllersEmulationMode::Quest1Touch => "1PALCXXXX00000_Controller", // 1PALCLC left, 1PALCRC right ControllersEmulationMode::Quest2Touch => "1WMHH000X00000_Controller", @@ -258,8 +258,8 @@ pub extern "C" fn set_device_openvr_props(instance_ptr: *mut c_void, device_id: }; // Per-device props - match &settings.headset.emulation_mode { - HeadsetEmulationMode::RiftS => { + match &settings.inputs.emulation_mode { + HmdEmulationMode::RiftS => { set_prop(TrackingSystemNameString, "oculus"); set_prop(ModelNumberString, "Oculus Rift S"); set_prop(ManufacturerNameString, "Oculus"); @@ -267,7 +267,7 @@ pub extern "C" fn set_device_openvr_props(instance_ptr: *mut c_void, device_id: set_prop(DriverVersionString, "1.42.0"); set_icons("{oculus}/icons/rifts_headset"); } - HeadsetEmulationMode::Quest1 => { + HmdEmulationMode::Quest1 => { set_prop(TrackingSystemNameString, "oculus"); set_prop(ModelNumberString, "Oculus Quest"); set_prop(ManufacturerNameString, "Oculus"); @@ -275,7 +275,7 @@ pub extern "C" fn set_device_openvr_props(instance_ptr: *mut c_void, device_id: set_prop(DriverVersionString, "1.111.0"); set_oculus_common_headset_props(); } - HeadsetEmulationMode::Quest2 => { + HmdEmulationMode::Quest2 => { set_prop(TrackingSystemNameString, "oculus"); set_prop(ModelNumberString, "Miramar"); set_prop(ManufacturerNameString, "Oculus"); @@ -283,7 +283,7 @@ pub extern "C" fn set_device_openvr_props(instance_ptr: *mut c_void, device_id: set_prop(DriverVersionString, "1.55.0"); set_oculus_common_headset_props(); } - HeadsetEmulationMode::QuestPro => { + HmdEmulationMode::QuestPro => { set_prop(TrackingSystemNameString, "oculus"); set_prop(ModelNumberString, "Meta Quest Pro"); set_prop(ManufacturerNameString, "Oculus"); @@ -291,7 +291,7 @@ pub extern "C" fn set_device_openvr_props(instance_ptr: *mut c_void, device_id: set_prop(DriverVersionString, "1.55.0"); set_oculus_common_headset_props(); } - HeadsetEmulationMode::Vive => { + HmdEmulationMode::Vive => { set_prop(TrackingSystemNameString, "Vive Tracker"); set_prop(ModelNumberString, "ALVR driver server"); set_prop(ManufacturerNameString, "HTC"); @@ -300,7 +300,7 @@ pub extern "C" fn set_device_openvr_props(instance_ptr: *mut c_void, device_id: set_prop(DriverVersionString, ""); set_icons("{htc}/icons/vive_headset"); } - HeadsetEmulationMode::Custom { .. } => (), + HmdEmulationMode::Custom { .. } => (), } set_prop(UserIpdMetersFloat, "0.063"); @@ -320,7 +320,7 @@ pub extern "C" fn set_device_openvr_props(instance_ptr: *mut c_void, device_id: set_prop(DeviceProvidesBatteryStatusBool, "true"); set_prop(ContainsProximitySensorBool, "true"); - for prop in &settings.headset.extra_openvr_props { + for prop in &settings.inputs.extra_openvr_props { set_prop(prop.key, &prop.value); } } else if device_id == *HAND_LEFT_ID @@ -332,7 +332,7 @@ pub extern "C" fn set_device_openvr_props(instance_ptr: *mut c_void, device_id: let right_hand = device_id == *HAND_RIGHT_ID || device_id == *HAND_TRACKER_RIGHT_ID; let full_skeletal_hand = device_id == *HAND_TRACKER_LEFT_ID || device_id == *HAND_TRACKER_RIGHT_ID; - if let Switch::Enabled(config) = &settings.headset.controllers { + if let Switch::Enabled(config) = &settings.inputs.controllers { // Closure for all the common Oculus/Meta controller properties let set_oculus_common_props = || { set_prop(TrackingSystemNameString, "oculus"); diff --git a/alvr/server_openvr/src/tracking.rs b/alvr/server_openvr/src/tracking.rs index 3ae647c4cd..6901119086 100644 --- a/alvr/server_openvr/src/tracking.rs +++ b/alvr/server_openvr/src/tracking.rs @@ -6,7 +6,7 @@ use alvr_common::{ glam::{EulerRot, Quat, Vec3}, settings_schema::Switch, }; -use alvr_session::{ControllersConfig, HeadsetConfig}; +use alvr_session::{ControllersConfig, InputsConfig}; use std::{ f32::consts::{FRAC_PI_2, PI}, sync::LazyLock, @@ -70,7 +70,7 @@ pub fn to_ffi_view_params(params: ViewParams) -> FfiViewParams { } } -fn get_hand_skeleton_offsets(config: &HeadsetConfig) -> (Pose, Pose) { +fn get_hand_skeleton_offsets(config: &InputsConfig) -> (Pose, Pose) { let left_offset; let right_offset; if let Switch::Enabled(controllers) = &config.controllers { @@ -121,7 +121,7 @@ fn to_ffi_skeleton(skeleton: &[Pose; 31]) -> FfiHandSkeleton { } pub fn to_openvr_ffi_hand_skeleton( - config: &HeadsetConfig, + config: &InputsConfig, device_id: u64, hand_skeleton: &[Pose; 26], ) -> FfiHandSkeleton { diff --git a/alvr/session/src/lib.rs b/alvr/session/src/lib.rs index 0a84ceac57..dbb7ff5d6d 100644 --- a/alvr/session/src/lib.rs +++ b/alvr/session/src/lib.rs @@ -645,6 +645,6 @@ mod tests { let settings = session.to_settings(); assert_eq!(settings.video.preferred_fps, 60.0); - assert!(settings.headset.controllers.as_option().is_none()); + assert!(settings.inputs.controllers.as_option().is_none()); } } diff --git a/alvr/session/src/settings.rs b/alvr/session/src/settings.rs index 988d9a3ab8..7d8dd8797a 100644 --- a/alvr/session/src/settings.rs +++ b/alvr/session/src/settings.rs @@ -862,7 +862,7 @@ pub struct AudioConfig { } #[derive(SettingsSchema, Serialize, Deserialize, Clone)] -pub enum HeadsetEmulationMode { +pub enum HmdEmulationMode { #[schema(strings(display_name = "Rift S"))] RiftS, #[schema(strings(display_name = "Quest 1"))] @@ -872,32 +872,14 @@ pub enum HeadsetEmulationMode { #[schema(strings(display_name = "Quest Pro"))] QuestPro, Vive, - Custom { - serial_number: String, - }, } #[derive(SettingsSchema, Serialize, Deserialize, Clone, PartialEq)] -pub enum FaceTrackingSourcesConfig { +pub enum FaceTrackingConfig { PreferEyeTrackingOnly, PreferFullFaceTracking, } -#[derive(SettingsSchema, Serialize, Deserialize, Clone)] -pub enum FaceTrackingSinkConfig { - #[schema(strings(display_name = "VRChat Eye OSC"))] - VrchatEyeOsc { port: u16 }, - #[schema(strings(display_name = "VRCFaceTracking"))] - VrcFaceTracking, -} - -#[derive(SettingsSchema, Serialize, Deserialize, Clone)] -#[schema(collapsible)] -pub struct FaceTrackingConfig { - pub sources: FaceTrackingSourcesConfig, - pub sink: FaceTrackingSinkConfig, -} - #[derive(SettingsSchema, Serialize, Deserialize, Clone, PartialEq, Default)] pub struct BodyTrackingMetaConfig { pub prefer_full_body: bool, @@ -924,40 +906,15 @@ pub enum BodyTrackingBDConfig { ObjectTracking, } -#[derive(SettingsSchema, Serialize, Deserialize, Clone, PartialEq)] -pub struct BodyTrackingSourcesConfig { - pub meta: BodyTrackingMetaConfig, - pub bd: BodyTrackingBDConfig, -} - -#[derive(SettingsSchema, Serialize, Deserialize, Clone)] -pub enum BodyTrackingSinkConfig { - #[schema(strings(display_name = "Fake Vive Trackers"))] - FakeViveTracker, - #[schema(strings(display_name = "VRChat Body OSC"))] - VrchatBodyOsc { port: u16 }, -} - #[derive(SettingsSchema, Serialize, Deserialize, Clone)] #[schema(collapsible)] pub struct BodyTrackingConfig { - pub sources: BodyTrackingSourcesConfig, - pub sink: BodyTrackingSinkConfig, #[schema(strings(help = "Turn this off to temporarily pause tracking."))] #[schema(flag = "real-time")] pub tracked: bool, -} -#[derive(SettingsSchema, Serialize, Deserialize, Clone)] -#[schema(collapsible)] -pub struct VMCConfig { - pub host: String, - pub port: u16, - #[schema(strings(help = "Turn this off to temporarily pause sending data."))] - #[schema(flag = "real-time")] - pub publish: bool, - #[schema(flag = "real-time")] - pub orientation_correction: bool, + pub meta: BodyTrackingMetaConfig, + pub bd: BodyTrackingBDConfig, } #[derive(SettingsSchema, Serialize, Deserialize, Clone, PartialEq, Eq)] @@ -980,12 +937,6 @@ pub enum ControllersEmulationMode { ValveIndex, #[schema(strings(display_name = "Vive Wand"))] ViveWand, - #[schema(strings(display_name = "Vive Tracker"))] - ViveTracker, - Custom { - serial_number: String, - button_set: Vec, - }, } #[derive(SettingsSchema, Serialize, Deserialize, Clone, Copy)] @@ -1110,31 +1061,8 @@ pub struct HandTrackingInteractionConfig { pub repeat_delay: u32, } -#[derive(SettingsSchema, Serialize, Deserialize, Clone)] -#[schema(collapsible)] -pub struct HapticsConfig { - #[schema(flag = "real-time")] - #[schema(gui(slider(min = 0.0, max = 5.0, step = 0.1)))] - pub intensity_multiplier: f32, - - #[schema(flag = "real-time")] - #[schema(gui(slider(min = 0.0, max = 1.0, step = 0.01)))] - pub amplitude_curve: f32, - - #[schema(strings(display_name = "Minimum duration"))] - #[schema(flag = "real-time")] - #[schema(gui(slider(min = 0.0, max = 0.1, step = 0.001)), suffix = "s")] - pub min_duration_s: f32, -} - #[derive(SettingsSchema, Serialize, Deserialize, Clone)] pub struct HandSkeletonConfig { - #[schema(flag = "steamvr-restart")] - #[schema(strings( - help = r"Enabling this will use separate tracker objects with the full skeletal tracking level when hand tracking is detected. This is required for VRChat hand tracking." - ))] - pub steamvr_input_2_0: bool, - #[schema(flag = "real-time")] #[schema(strings( help = r"Predict hand skeleton to make it less floaty. It may make hands too jittery." @@ -1149,10 +1077,10 @@ pub struct ControllersConfig { #[schema(flag = "real-time")] pub tracked: bool, - #[schema(flag = "steamvr-restart")] #[schema(strings( help = "Enabling this passes skeletal hand data (finger tracking) to SteamVR." ))] + #[schema(flag = "real-time")] pub hand_skeleton: Switch, #[schema(flag = "real-time")] @@ -1162,23 +1090,14 @@ pub struct ControllersConfig { pub hand_tracking_interaction: Switch, #[schema(strings( - display_name = "Prediction", - help = r"Higher values make the controllers track smoother. -Technically, this is the time (counted in frames) between pose submitted to SteamVR and the corresponding virtual vsync happens. -Currently this cannot be reliably estimated automatically. The correct value should be 2 but 3 is default for smoother tracking at the cost of slight lag." + help = r"Track hand skeleton while holding controllers. This will reduce hand tracking frequency to 30Hz. +Because of runtime limitations, this option is ignored when body tracking is active." ))] - #[schema(gui(slider(min = 1.0, max = 10.0, logarithmic)), suffix = "frames")] - pub steamvr_pipeline_frames: f32, - - #[schema(flag = "real-time")] - pub haptics: Switch, + pub multimodal_tracking: bool, #[schema(flag = "steamvr-restart")] pub emulation_mode: ControllersEmulationMode, - #[schema(flag = "steamvr-restart")] - pub extra_openvr_props: Vec, - #[schema(flag = "real-time")] // note: logarithmic scale seems to be glitchy for this control #[schema(gui(slider(min = 0.0, max = 1.0, step = 0.01)), suffix = "m/s")] @@ -1189,28 +1108,6 @@ Currently this cannot be reliably estimated automatically. The correct value sho #[schema(gui(slider(min = 0.0, max = 100.0, step = 1.0)), suffix = "°/s")] pub angular_velocity_cutoff: f32, - #[schema(flag = "real-time")] - #[schema(strings(help = "Right controller offset is mirrored horizontally"))] - // note: logarithmic scale seems to be glitchy for this control - #[schema(gui(slider(min = -0.5, max = 0.5, step = 0.001)), suffix = "m")] - pub left_controller_position_offset: [f32; 3], - - #[schema(flag = "real-time")] - #[schema(strings(help = "Right controller offset is mirrored horizontally"))] - #[schema(gui(slider(min = -180.0, max = 180.0, step = 1.0)), suffix = "°")] - pub left_controller_rotation_offset: [f32; 3], - - #[schema(flag = "real-time")] - #[schema(strings(help = "Right controller offset is mirrored horizontally"))] - // note: logarithmic scale seems to be glitchy for this control - #[schema(gui(slider(min = -0.5, max = 0.5, step = 0.001)), suffix = "m")] - pub left_hand_tracking_position_offset: [f32; 3], - - #[schema(flag = "real-time")] - #[schema(strings(help = "Right controller offset is mirrored horizontally"))] - #[schema(gui(slider(min = -180.0, max = 180.0, step = 1.0)), suffix = "°")] - pub left_hand_tracking_rotation_offset: [f32; 3], - #[schema(strings(help = "List of OpenXR-syle paths"))] pub button_mappings: Option)>>, @@ -1235,20 +1132,71 @@ pub enum RotationRecenteringMode { } #[derive(SettingsSchema, Serialize, Deserialize, Clone, Copy)] -pub struct MultimodalTracking { - pub enabled: bool, +pub enum InputTrackerType { + Head, + LeftController, + RightController, + LeftHandSkeleton, + RightHandSkeleton, + LeftDetachedController, + RightDetachedController, + Chest, + LeftShoulder, + RightShoulder, + LeftElbow, + RightElbow, + LeftWrist, + RightWrist, + Waist, + LeftKnee, + RightKnee, + LeftAnkle, + RightAnkle, + LeftFoot, + RightFoot, + Generic1, + Generic2, + Generic3, + Generic4, + Generic5, +} - #[schema(flag = "steamvr-restart")] - #[schema(strings( - display_name = "Map non-held controllers to SteamVR trackers", - help = "Non-held controllers are mapped to left and right feet. -This will be configurable in the future." - ))] - pub detached_controllers_steamvr_sink: bool, +#[derive(SettingsSchema, Serialize, Deserialize, Clone, Copy)] +pub enum OutputTrackerType { + Head, + LeftController, + RightController, + LeftHandSkeleton, + RightHandSkeleton, + Chest, + LeftShoulder, + RightShoulder, + LeftElbow, + RightElbow, + LeftWrist, + RightWrist, + Waist, + LeftKnee, + RightKnee, + LeftAnkle, + RightAnkle, + LeftFoot, + RightFoot, +} + +#[derive(SettingsSchema, Serialize, Deserialize, Clone, Copy)] +pub struct TrackerMapping { + input: InputTrackerType, + output: OutputTrackerType, + + #[schema(suffix = "m")] + position_offset: [f32; 3], + #[schema(suffix = "°")] + rotation_offset: [f32; 3], } #[derive(SettingsSchema, Serialize, Deserialize, Clone)] -pub struct HeadsetConfig { +pub struct InputsConfig { #[schema(strings( help = r#"Disabled: the playspace origin is determined by the room-scale guardian setup. Local floor: the origin is on the floor and resets when long pressing the oculus button. @@ -1265,42 +1213,92 @@ Tilted: the world gets tilted when long pressing the oculus button. This is usef #[schema(flag = "real-time")] pub rotation_recentering_mode: RotationRecenteringMode, + #[schema(flag = "steamvr-restart")] + pub hmd_emulation_mode: HmdEmulationMode, + #[schema(flag = "steamvr-restart")] pub controllers: Switch, + pub face_tracking: Switch, + pub body_tracking: Switch, + + pub tracker_mappings: Vec, + + #[schema(strings( + help = "Maximum prediction for head and controllers. Used to avoid too much jitter during loading." + ))] + #[schema(gui(slider(min = 0, max = 200, step = 5)), suffix = "ms")] + pub max_prediction_ms: u64, +} +#[derive(SettingsSchema, Serialize, Deserialize, Clone)] +pub struct SteamvrLauncherConfig { + #[schema(strings( + display_name = "Open and close SteamVR automatically", + help = "Launches SteamVR automatically when the ALVR dashboard is opened, and closes it when the dashboard is closed." + ))] + pub open_close_with_dashboard: bool, + + #[cfg_attr( + windows, + schema(strings(help = "Directly start the VR server, bypassing Steam. \ + Will run start_server.bat if it exists alongside session.json, and try to automatically find SteamVR otherwise.")) + )] + #[cfg_attr( + not(windows), + schema(strings(help = "Directly start the VR server, bypassing Steam. \ + Will run start_server.sh if it exists alongside session.json, and try to automatically find SteamVR otherwise.")) + )] + pub direct_launch: bool, +} + +#[derive(SettingsSchema, Serialize, Deserialize, Clone)] +pub struct SteamvrTrackerConfig { #[schema(flag = "steamvr-restart")] - pub emulation_mode: HeadsetEmulationMode, + pub tracker_type: OutputTrackerType, #[schema(flag = "steamvr-restart")] pub extra_openvr_props: Vec, +} - #[schema(flag = "steamvr-restart")] - pub tracking_ref_only: bool, +#[derive(SettingsSchema, Serialize, Deserialize, Clone)] +pub struct SteamvrConfig { + pub launcher: SteamvrLauncherConfig, #[schema(flag = "steamvr-restart")] - pub enable_vive_tracker_proxy: bool, - - pub face_tracking: Switch, + pub enabled_trackers: Vec, #[schema(flag = "steamvr-restart")] #[schema(strings( - help = r"Track hand skeleton while holding controllers. This will reduce hand tracking frequency to 30Hz. -Because of runtime limitations, this option is ignored when body tracking is active." + help = r"Enabling this will use separate tracker objects with the full skeletal tracking level when hand tracking is detected. This is required for VRChat hand tracking." + ))] + pub steamvr_input_2_0: bool, + + #[schema(strings( + display_name = "Controllers prediction", + help = r"Higher values make the controllers track smoother. +Technically, this is the time (counted in frames) between pose submitted to SteamVR and the corresponding virtual vsync happens. +Currently this cannot be reliably estimated automatically. The correct value should be 2 but 3 is default for smoother tracking at the cost of slight lag." ))] - pub multimodal_tracking: Switch, + #[schema(gui(slider(min = 1.0, max = 10.0, logarithmic)), suffix = "frames")] + pub steamvr_pipeline_frames: f32, #[schema(flag = "steamvr-restart")] - pub body_tracking: Switch, + pub tracking_ref_only: bool, #[schema(flag = "steamvr-restart")] - #[schema(strings(display_name = "VMC"))] - pub vmc: Switch, + pub enable_vive_tracker_proxy: bool, - #[schema(strings( - help = "Maximum prediction for head and controllers. Used to avoid too much jitter during loading." - ))] - #[schema(gui(slider(min = 0, max = 200, step = 5)), suffix = "ms")] - pub max_prediction_ms: u64, + #[schema(flag = "real-time")] + pub left_controller_position_offset: [f32; 3], + + #[schema(flag = "real-time")] + pub left_controller_rotation_offset: [f32; 3], + + #[schema(flag = "real-time")] + pub left_hand_tracking_position_offset: [f32; 3], + + #[schema(flag = "real-time")] + pub left_hand_tracking_rotation_offset: [f32; 3], } #[derive(SettingsSchema, Serialize, Deserialize, Clone, Copy)] @@ -1321,6 +1319,14 @@ pub struct DiscoveryConfig { pub auto_trust_clients: bool, } +#[derive(SettingsSchema, Serialize, Deserialize, Clone)] +pub struct WiredClientAutoLaunchConfig { + #[schema(strings( + help = "Delay in seconds to wait after booting the headset before trying to launch the client." + ))] + pub boot_delay: u32, +} + #[derive(SettingsSchema, Serialize, Deserialize, Clone, Copy)] pub enum SocketBufferSize { Default, @@ -1328,12 +1334,28 @@ pub enum SocketBufferSize { Custom(#[schema(suffix = "B")] u32), } -#[derive(SettingsSchema, Serialize, Deserialize, Clone)] -pub struct WiredClientAutoLaunchConfig { - #[schema(strings( - help = "Delay in seconds to wait after booting the headset before trying to launch the client." - ))] - pub boot_delay: u32, +#[derive(SettingsSchema, Serialize, Deserialize, Clone, Copy)] +#[repr(u8)] +#[schema(gui = "button_group")] +pub enum DropProbability { + Low = 0x01, + Medium = 0x10, + High = 0x11, +} + +#[derive(SettingsSchema, Serialize, Deserialize, Clone, Copy)] +pub enum DscpTos { + BestEffort, + + ClassSelector(#[schema(gui(slider(min = 1, max = 7)))] u8), + + AssuredForwarding { + #[schema(gui(slider(min = 1, max = 4)))] + class: u8, + drop_probability: DropProbability, + }, + + ExpeditedForwarding, } #[derive(SettingsSchema, Serialize, Deserialize, Clone)] @@ -1431,28 +1453,42 @@ This could happen on TCP. A IDR frame is requested in this case."# pub dscp: Option, } -#[derive(SettingsSchema, Serialize, Deserialize, Clone, Copy)] -#[repr(u8)] -#[schema(gui = "button_group")] -pub enum DropProbability { - Low = 0x01, - Medium = 0x10, - High = 0x11, +#[derive(SettingsSchema, Serialize, Deserialize, Clone)] +#[schema(collapsible)] +pub struct HapticsConfig { + #[schema(flag = "real-time")] + #[schema(gui(slider(min = 0.0, max = 5.0, step = 0.1)))] + pub intensity_multiplier: f32, + + #[schema(flag = "real-time")] + #[schema(gui(slider(min = 0.0, max = 1.0, step = 0.01)))] + pub amplitude_curve: f32, + + #[schema(strings(display_name = "Minimum duration"))] + #[schema(flag = "real-time")] + #[schema(gui(slider(min = 0.0, max = 0.1, step = 0.001)), suffix = "s")] + pub min_duration_s: f32, } -#[derive(SettingsSchema, Serialize, Deserialize, Clone, Copy)] -pub enum DscpTos { - BestEffort, +#[derive(SettingsSchema, Serialize, Deserialize, Clone)] +pub enum FaceTrackingOscOutputConfig { + #[schema(strings(display_name = "VRChat Eye OSC"))] + VrchatEyes { port: u16 }, + #[schema(strings(display_name = "VRCFaceTracking"))] + VrcFaceTracking, +} - ClassSelector(#[schema(gui(slider(min = 1, max = 7)))] u8), +#[derive(SettingsSchema, Serialize, Deserialize, Clone)] +pub struct VMCConfig { + pub host: String, + pub port: u16, - AssuredForwarding { - #[schema(gui(slider(min = 1, max = 4)))] - class: u8, - drop_probability: DropProbability, - }, + #[schema(strings(help = "Turn this off to temporarily pause sending data."))] + #[schema(flag = "real-time")] + pub publish: bool, - ExpeditedForwarding, + #[schema(flag = "real-time")] + pub orientation_correction: bool, } #[derive(SettingsSchema, Serialize, Deserialize, Clone)] @@ -1495,27 +1531,6 @@ pub struct LoggingConfig { pub debug_groups: DebugGroupsConfig, } -#[derive(SettingsSchema, Serialize, Deserialize, Clone)] -pub struct SteamvrLauncher { - #[schema(strings( - display_name = "Open and close SteamVR automatically", - help = "Launches SteamVR automatically when the ALVR dashboard is opened, and closes it when the dashboard is closed." - ))] - pub open_close_steamvr_with_dashboard: bool, - - #[cfg_attr( - windows, - schema(strings(help = "Directly start the VR server, bypassing Steam. \ - Will run start_server.bat if it exists alongside session.json, and try to automatically find SteamVR otherwise.")) - )] - #[cfg_attr( - not(windows), - schema(strings(help = "Directly start the VR server, bypassing Steam. \ - Will run start_server.sh if it exists alongside session.json, and try to automatically find SteamVR otherwise.")) - )] - pub direct_launch: bool, -} - #[derive(SettingsSchema, Serialize, Deserialize, Clone)] pub struct RollingVideoFilesConfig { #[schema(strings(display_name = "Duration"))] @@ -1555,10 +1570,18 @@ pub struct NewVersionPopupConfig { #[derive(SettingsSchema, Serialize, Deserialize, Clone)] pub struct ExtraConfig { - #[schema(strings(display_name = "SteamVR Launcher"))] - pub steamvr_launcher: SteamvrLauncher, + #[schema(flag = "real-time")] + pub haptics: Switch, + + pub face_tracking_osc_output: FaceTrackingOscOutputConfig, + pub vrchat_body_osc_port: Switch, + + #[schema(strings(display_name = "VMC"))] + pub vmc: Switch, + pub capture: CaptureConfig, pub logging: LoggingConfig, + #[cfg_attr(not(target_os = "linux"), schema(flag = "hidden"))] pub patches: Patches, @@ -1576,7 +1599,8 @@ It does not update in real time.") pub struct Settings { pub video: VideoConfig, pub audio: AudioConfig, - pub headset: HeadsetConfig, + pub inputs: InputsConfig, + pub steamvr: SteamvrConfig, pub connection: ConnectionConfig, pub extra: ExtraConfig, } @@ -1598,21 +1622,49 @@ pub fn session_settings_default() -> SettingsDefault { Index: 0, variant: CustomAudioDeviceConfigDefaultVariant::NameSubstring, }; - let default_custom_openvr_props = VectorDefault { - gui_collapsed: true, - element: OpenvrPropertyDefault { - key: OpenvrPropKeyDefault { - variant: OpenvrPropKeyDefaultVariant::TrackingSystemNameString, - }, - value: "".into(), - }, - content: vec![], - }; let socket_buffer = SocketBufferSizeDefault { Custom: 100000, variant: SocketBufferSizeDefaultVariant::Maximum, }; + fn tracker_mapping_default( + input: InputTrackerTypeDefaultVariant, + output: OutputTrackerTypeDefaultVariant, + ) -> TrackerMappingDefault { + TrackerMappingDefault { + input: InputTrackerTypeDefault { variant: input }, + output: OutputTrackerTypeDefault { variant: output }, + position_offset: ArrayDefault { + gui_collapsed: true, + content: [0.0, 0.0, 0.0], + }, + rotation_offset: ArrayDefault { + gui_collapsed: true, + content: [0.0, 0.0, 0.0], + }, + } + } + + fn steamvr_tracker_default( + tracker_type: OutputTrackerTypeDefaultVariant, + ) -> SteamvrTrackerConfigDefault { + SteamvrTrackerConfigDefault { + tracker_type: OutputTrackerTypeDefault { + variant: tracker_type, + }, + extra_openvr_props: VectorDefault { + gui_collapsed: true, + element: OpenvrPropertyDefault { + key: OpenvrPropKeyDefault { + variant: OpenvrPropKeyDefaultVariant::TrackingSystemNameString, + }, + value: "".into(), + }, + content: vec![], + }, + } + } + SettingsDefault { video: VideoConfigDefault { passthrough: SwitchDefault { @@ -1904,69 +1956,16 @@ pub fn session_settings_default() -> SettingsDefault { }, }, }, - headset: HeadsetConfigDefault { - emulation_mode: HeadsetEmulationModeDefault { - Custom: HeadsetEmulationModeCustomDefault { - serial_number: "Unknown".into(), - }, - variant: HeadsetEmulationModeDefaultVariant::Quest2, - }, - extra_openvr_props: default_custom_openvr_props.clone(), - tracking_ref_only: false, - enable_vive_tracker_proxy: false, - face_tracking: SwitchDefault { - enabled: false, - content: FaceTrackingConfigDefault { - gui_collapsed: true, - sources: FaceTrackingSourcesConfigDefault { - variant: FaceTrackingSourcesConfigDefaultVariant::PreferFullFaceTracking, - }, - sink: FaceTrackingSinkConfigDefault { - VrchatEyeOsc: FaceTrackingSinkConfigVrchatEyeOscDefault { port: 9000 }, - variant: FaceTrackingSinkConfigDefaultVariant::VrchatEyeOsc, - }, - }, - }, - multimodal_tracking: SwitchDefault { - enabled: false, - content: MultimodalTrackingDefault { - enabled: true, - detached_controllers_steamvr_sink: false, - }, + inputs: InputsConfigDefault { + position_recentering_mode: PositionRecenteringModeDefault { + Local: PositionRecenteringModeLocalDefault { view_height: 1.5 }, + variant: PositionRecenteringModeDefaultVariant::LocalFloor, }, - body_tracking: SwitchDefault { - enabled: false, - content: BodyTrackingConfigDefault { - gui_collapsed: true, - sources: BodyTrackingSourcesConfigDefault { - meta: BodyTrackingMetaConfigDefault { - prefer_full_body: true, - prefer_high_fidelity: true, - }, - bd: BodyTrackingBDConfigDefault { - BodyTracking: BodyTrackingBDConfigBodyTrackingDefault { - high_accuracy: true, - prompt_calibration_on_start: true, - }, - variant: BodyTrackingBDConfigDefaultVariant::BodyTracking, - }, - }, - sink: BodyTrackingSinkConfigDefault { - VrchatBodyOsc: BodyTrackingSinkConfigVrchatBodyOscDefault { port: 9000 }, - variant: BodyTrackingSinkConfigDefaultVariant::FakeViveTracker, - }, - tracked: true, - }, + rotation_recentering_mode: RotationRecenteringModeDefault { + variant: RotationRecenteringModeDefaultVariant::Yaw, }, - vmc: SwitchDefault { - enabled: false, - content: VMCConfigDefault { - gui_collapsed: true, - host: "127.0.0.1".into(), - port: 39539, - publish: true, - orientation_correction: true, - }, + hmd_emulation_mode: HmdEmulationModeDefault { + variant: HmdEmulationModeDefaultVariant::Quest2, }, controllers: SwitchDefault { enabled: true, @@ -1975,23 +1974,29 @@ pub fn session_settings_default() -> SettingsDefault { tracked: true, hand_skeleton: SwitchDefault { enabled: true, - content: HandSkeletonConfigDefault { - steamvr_input_2_0: true, - predict: false, + content: HandSkeletonConfigDefault { predict: false }, + }, + hand_tracking_interaction: SwitchDefault { + enabled: false, + content: HandTrackingInteractionConfigDefault { + only_touch: false, + pinch_touch_distance: 0.0, + pinch_trigger_distance: 0.25, + curl_touch_distance: 2.0, + curl_trigger_distance: 2.5, + joystick_deadzone: 40.0, + joystick_offset_horizontal: 0.0, + joystick_offset_vertical: 0.0, + joystick_range: 1.0, + repeat_delay: 100, + activation_delay: 50, + deactivation_delay: 100, }, }, + multimodal_tracking: false, emulation_mode: ControllersEmulationModeDefault { - Custom: ControllersEmulationModeCustomDefault { - serial_number: "ALVR Controller".into(), - button_set: VectorDefault { - gui_collapsed: false, - element: "/user/hand/left/input/a/click".into(), - content: vec![], - }, - }, variant: ControllersEmulationModeDefaultVariant::Quest2Touch, }, - extra_openvr_props: default_custom_openvr_props, button_mappings: OptionalDefault { set: false, content: DictionaryDefault { @@ -2036,62 +2041,110 @@ pub fn session_settings_default() -> SettingsDefault { }, force_threshold: 0.8, }, - hand_tracking_interaction: SwitchDefault { - enabled: false, - content: HandTrackingInteractionConfigDefault { - only_touch: false, - pinch_touch_distance: 0.0, - pinch_trigger_distance: 0.25, - curl_touch_distance: 2.0, - curl_trigger_distance: 2.5, - joystick_deadzone: 40.0, - joystick_offset_horizontal: 0.0, - joystick_offset_vertical: 0.0, - joystick_range: 1.0, - repeat_delay: 100, - activation_delay: 50, - deactivation_delay: 100, - }, - }, - steamvr_pipeline_frames: 2.1, linear_velocity_cutoff: 0.05, angular_velocity_cutoff: 10.0, - left_controller_position_offset: ArrayDefault { - gui_collapsed: true, - content: [0.0, 0.0, -0.11], - }, - left_controller_rotation_offset: ArrayDefault { - gui_collapsed: true, - content: [0.0; 3], - }, - left_hand_tracking_position_offset: ArrayDefault { - gui_collapsed: true, - content: [0.04, -0.02, -0.13], - }, - left_hand_tracking_rotation_offset: ArrayDefault { - gui_collapsed: true, - content: [0.0, -45.0, -90.0], + }, + }, + face_tracking: SwitchDefault { + enabled: false, + content: FaceTrackingConfigDefault { + variant: FaceTrackingConfigDefaultVariant::PreferFullFaceTracking, + }, + }, + body_tracking: SwitchDefault { + enabled: false, + content: BodyTrackingConfigDefault { + gui_collapsed: true, + tracked: true, + meta: BodyTrackingMetaConfigDefault { + prefer_full_body: true, + prefer_high_fidelity: true, }, - haptics: SwitchDefault { - enabled: true, - content: HapticsConfigDefault { - gui_collapsed: true, - intensity_multiplier: 1.0, - amplitude_curve: 1.0, - min_duration_s: 0.01, + bd: BodyTrackingBDConfigDefault { + BodyTracking: BodyTrackingBDConfigBodyTrackingDefault { + high_accuracy: true, + prompt_calibration_on_start: true, }, + variant: BodyTrackingBDConfigDefaultVariant::BodyTracking, }, }, }, - position_recentering_mode: PositionRecenteringModeDefault { - Local: PositionRecenteringModeLocalDefault { view_height: 1.5 }, - variant: PositionRecenteringModeDefaultVariant::LocalFloor, - }, - rotation_recentering_mode: RotationRecenteringModeDefault { - variant: RotationRecenteringModeDefaultVariant::Yaw, + tracker_mappings: VectorDefault { + gui_collapsed: true, + element: tracker_mapping_default( + InputTrackerTypeDefaultVariant::Head, + OutputTrackerTypeDefaultVariant::Head, + ), + content: vec![ + tracker_mapping_default( + InputTrackerTypeDefaultVariant::LeftDetachedController, + OutputTrackerTypeDefaultVariant::LeftFoot, + ), + tracker_mapping_default( + InputTrackerTypeDefaultVariant::RightDetachedController, + OutputTrackerTypeDefaultVariant::RightFoot, + ), + tracker_mapping_default( + InputTrackerTypeDefaultVariant::Generic1, + OutputTrackerTypeDefaultVariant::Waist, + ), + tracker_mapping_default( + InputTrackerTypeDefaultVariant::Generic2, + OutputTrackerTypeDefaultVariant::LeftFoot, + ), + tracker_mapping_default( + InputTrackerTypeDefaultVariant::Generic3, + OutputTrackerTypeDefaultVariant::RightFoot, + ), + tracker_mapping_default( + InputTrackerTypeDefaultVariant::Generic4, + OutputTrackerTypeDefaultVariant::LeftElbow, + ), + tracker_mapping_default( + InputTrackerTypeDefaultVariant::Generic5, + OutputTrackerTypeDefaultVariant::RightElbow, + ), + ], }, max_prediction_ms: 100, }, + steamvr: SteamvrConfigDefault { + launcher: SteamvrLauncherConfigDefault { + open_close_with_dashboard: false, + direct_launch: false, + }, + enabled_trackers: VectorDefault { + gui_collapsed: true, + element: steamvr_tracker_default(OutputTrackerTypeDefaultVariant::Waist), + content: vec![ + steamvr_tracker_default(OutputTrackerTypeDefaultVariant::Head), + steamvr_tracker_default(OutputTrackerTypeDefaultVariant::LeftController), + steamvr_tracker_default(OutputTrackerTypeDefaultVariant::RightController), + steamvr_tracker_default(OutputTrackerTypeDefaultVariant::LeftHandSkeleton), + steamvr_tracker_default(OutputTrackerTypeDefaultVariant::RightHandSkeleton), + ], + }, + steamvr_input_2_0: true, + steamvr_pipeline_frames: 2.1, + tracking_ref_only: false, + enable_vive_tracker_proxy: false, + left_controller_position_offset: ArrayDefault { + gui_collapsed: true, + content: [0.0, 0.0, -0.11], + }, + left_controller_rotation_offset: ArrayDefault { + gui_collapsed: true, + content: [0.0, 0.0, 0.0], + }, + left_hand_tracking_position_offset: ArrayDefault { + gui_collapsed: true, + content: [0.04, -0.02, -0.13], + }, + left_hand_tracking_rotation_offset: ArrayDefault { + gui_collapsed: true, + content: [0.0, -45.0, -90.0], + }, + }, connection: ConnectionConfigDefault { stream_protocol: SocketProtocolDefault { variant: SocketProtocolDefaultVariant::Udp, @@ -2144,6 +2197,32 @@ pub fn session_settings_default() -> SettingsDefault { statistics_history_size: 256, }, extra: ExtraConfigDefault { + haptics: SwitchDefault { + enabled: true, + content: HapticsConfigDefault { + gui_collapsed: true, + intensity_multiplier: 1.0, + amplitude_curve: 1.0, + min_duration_s: 0.01, + }, + }, + face_tracking_osc_output: FaceTrackingOscOutputConfigDefault { + variant: FaceTrackingOscOutputConfigDefaultVariant::VrchatEyes, + VrchatEyes: FaceTrackingOscOutputConfigVrchatEyesDefault { port: 9000 }, + }, + vrchat_body_osc_port: SwitchDefault { + enabled: false, + content: 9000, + }, + vmc: SwitchDefault { + enabled: false, + content: VMCConfigDefault { + host: "127.0.0.1".into(), + port: 39539, + publish: true, + orientation_correction: true, + }, + }, logging: LoggingConfigDefault { client_log_report_level: SwitchDefault { enabled: true, @@ -2183,10 +2262,6 @@ pub fn session_settings_default() -> SettingsDefault { decoder: false, }, }, - steamvr_launcher: SteamvrLauncherDefault { - open_close_steamvr_with_dashboard: false, - direct_launch: false, - }, capture: CaptureConfigDefault { startup_video_recording: false, rolling_video_files: SwitchDefault { From edd1e18b0aa362ac64dd023e8ac7eadf2fb7a0a6 Mon Sep 17 00:00:00 2001 From: Riccardo Zaglia Date: Wed, 29 Oct 2025 23:34:03 +1000 Subject: [PATCH 2/2] Address some comments --- alvr/session/src/settings.rs | 93 +++++++++++++++++------------------- 1 file changed, 45 insertions(+), 48 deletions(-) diff --git a/alvr/session/src/settings.rs b/alvr/session/src/settings.rs index 7d8dd8797a..1a82b75829 100644 --- a/alvr/session/src/settings.rs +++ b/alvr/session/src/settings.rs @@ -1185,11 +1185,15 @@ pub enum OutputTrackerType { } #[derive(SettingsSchema, Serialize, Deserialize, Clone, Copy)] -pub struct TrackerMapping { - input: InputTrackerType, +pub struct TrackerConfig { + #[schema(flag = "steamvr-restart")] + #[schema(strings(help = "This is the tracker type as seen by SteamVR"))] output: OutputTrackerType, - #[schema(suffix = "m")] + #[schema(strings(help = "This is the tracker type where data comes from"))] + input: InputTrackerType, + + #[schema(suffix = "mm")] position_offset: [f32; 3], #[schema(suffix = "°")] rotation_offset: [f32; 3], @@ -1218,10 +1222,15 @@ Tilted: the world gets tilted when long pressing the oculus button. This is usef #[schema(flag = "steamvr-restart")] pub controllers: Switch, + pub face_tracking: Switch, pub body_tracking: Switch, - pub tracker_mappings: Vec, + #[schema(flag = "steamvr-restart")] + #[schema(strings( + help = "Head and controllers don't have to be added to this list to be enabled" + ))] + pub trackers: Vec, #[schema(strings( help = "Maximum prediction for head and controllers. Used to avoid too much jitter during loading." @@ -1252,12 +1261,12 @@ pub struct SteamvrLauncherConfig { } #[derive(SettingsSchema, Serialize, Deserialize, Clone)] -pub struct SteamvrTrackerConfig { +pub struct ExtraOpenvrPropsConfig { #[schema(flag = "steamvr-restart")] pub tracker_type: OutputTrackerType, #[schema(flag = "steamvr-restart")] - pub extra_openvr_props: Vec, + pub props: Vec, } #[derive(SettingsSchema, Serialize, Deserialize, Clone)] @@ -1265,7 +1274,7 @@ pub struct SteamvrConfig { pub launcher: SteamvrLauncherConfig, #[schema(flag = "steamvr-restart")] - pub enabled_trackers: Vec, + pub extra_openvr_props: Vec, #[schema(flag = "steamvr-restart")] #[schema(strings( @@ -1627,11 +1636,11 @@ pub fn session_settings_default() -> SettingsDefault { variant: SocketBufferSizeDefaultVariant::Maximum, }; - fn tracker_mapping_default( + fn tracker_config_default( input: InputTrackerTypeDefaultVariant, output: OutputTrackerTypeDefaultVariant, - ) -> TrackerMappingDefault { - TrackerMappingDefault { + ) -> TrackerConfigDefault { + TrackerConfigDefault { input: InputTrackerTypeDefault { variant: input }, output: OutputTrackerTypeDefault { variant: output }, position_offset: ArrayDefault { @@ -1645,26 +1654,6 @@ pub fn session_settings_default() -> SettingsDefault { } } - fn steamvr_tracker_default( - tracker_type: OutputTrackerTypeDefaultVariant, - ) -> SteamvrTrackerConfigDefault { - SteamvrTrackerConfigDefault { - tracker_type: OutputTrackerTypeDefault { - variant: tracker_type, - }, - extra_openvr_props: VectorDefault { - gui_collapsed: true, - element: OpenvrPropertyDefault { - key: OpenvrPropKeyDefault { - variant: OpenvrPropKeyDefaultVariant::TrackingSystemNameString, - }, - value: "".into(), - }, - content: vec![], - }, - } - } - SettingsDefault { video: VideoConfigDefault { passthrough: SwitchDefault { @@ -2069,38 +2058,38 @@ pub fn session_settings_default() -> SettingsDefault { }, }, }, - tracker_mappings: VectorDefault { + trackers: VectorDefault { gui_collapsed: true, - element: tracker_mapping_default( + element: tracker_config_default( InputTrackerTypeDefaultVariant::Head, OutputTrackerTypeDefaultVariant::Head, ), content: vec![ - tracker_mapping_default( + tracker_config_default( InputTrackerTypeDefaultVariant::LeftDetachedController, OutputTrackerTypeDefaultVariant::LeftFoot, ), - tracker_mapping_default( + tracker_config_default( InputTrackerTypeDefaultVariant::RightDetachedController, OutputTrackerTypeDefaultVariant::RightFoot, ), - tracker_mapping_default( + tracker_config_default( InputTrackerTypeDefaultVariant::Generic1, OutputTrackerTypeDefaultVariant::Waist, ), - tracker_mapping_default( + tracker_config_default( InputTrackerTypeDefaultVariant::Generic2, OutputTrackerTypeDefaultVariant::LeftFoot, ), - tracker_mapping_default( + tracker_config_default( InputTrackerTypeDefaultVariant::Generic3, OutputTrackerTypeDefaultVariant::RightFoot, ), - tracker_mapping_default( + tracker_config_default( InputTrackerTypeDefaultVariant::Generic4, OutputTrackerTypeDefaultVariant::LeftElbow, ), - tracker_mapping_default( + tracker_config_default( InputTrackerTypeDefaultVariant::Generic5, OutputTrackerTypeDefaultVariant::RightElbow, ), @@ -2113,16 +2102,24 @@ pub fn session_settings_default() -> SettingsDefault { open_close_with_dashboard: false, direct_launch: false, }, - enabled_trackers: VectorDefault { + extra_openvr_props: VectorDefault { gui_collapsed: true, - element: steamvr_tracker_default(OutputTrackerTypeDefaultVariant::Waist), - content: vec![ - steamvr_tracker_default(OutputTrackerTypeDefaultVariant::Head), - steamvr_tracker_default(OutputTrackerTypeDefaultVariant::LeftController), - steamvr_tracker_default(OutputTrackerTypeDefaultVariant::RightController), - steamvr_tracker_default(OutputTrackerTypeDefaultVariant::LeftHandSkeleton), - steamvr_tracker_default(OutputTrackerTypeDefaultVariant::RightHandSkeleton), - ], + element: ExtraOpenvrPropsConfigDefault { + tracker_type: OutputTrackerTypeDefault { + variant: OutputTrackerTypeDefaultVariant::Head, + }, + props: VectorDefault { + gui_collapsed: true, + element: OpenvrPropertyDefault { + key: OpenvrPropKeyDefault { + variant: OpenvrPropKeyDefaultVariant::TrackingSystemNameString, + }, + value: "".into(), + }, + content: vec![], + }, + }, + content: vec![], }, steamvr_input_2_0: true, steamvr_pipeline_frames: 2.1,