diff --git a/Cargo.lock b/Cargo.lock index 3a5abf79fb..acbd554930 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -180,7 +180,7 @@ dependencies = [ [[package]] name = "alvr_adb" -version = "21.0.0-dev10" +version = "21.0.0-dev11" dependencies = [ "alvr_common", "alvr_filesystem", @@ -193,7 +193,7 @@ dependencies = [ [[package]] name = "alvr_audio" -version = "21.0.0-dev10" +version = "21.0.0-dev11" dependencies = [ "alvr_common", "alvr_session", @@ -209,7 +209,7 @@ dependencies = [ [[package]] name = "alvr_client_core" -version = "21.0.0-dev10" +version = "21.0.0-dev11" dependencies = [ "alvr_audio", "alvr_common", @@ -231,7 +231,7 @@ dependencies = [ [[package]] name = "alvr_client_mock" -version = "21.0.0-dev10" +version = "21.0.0-dev11" dependencies = [ "alvr_client_core", "alvr_common", @@ -244,7 +244,7 @@ dependencies = [ [[package]] name = "alvr_client_openxr" -version = "21.0.0-dev10" +version = "21.0.0-dev11" dependencies = [ "alvr_client_core", "alvr_common", @@ -261,7 +261,7 @@ dependencies = [ [[package]] name = "alvr_common" -version = "21.0.0-dev10" +version = "21.0.0-dev11" dependencies = [ "anyhow", "backtrace", @@ -276,7 +276,7 @@ dependencies = [ [[package]] name = "alvr_dashboard" -version = "21.0.0-dev10" +version = "21.0.0-dev11" dependencies = [ "alvr_adb", "alvr_audio", @@ -308,7 +308,7 @@ dependencies = [ [[package]] name = "alvr_events" -version = "21.0.0-dev10" +version = "21.0.0-dev11" dependencies = [ "alvr_common", "alvr_packets", @@ -319,14 +319,14 @@ dependencies = [ [[package]] name = "alvr_filesystem" -version = "21.0.0-dev10" +version = "21.0.0-dev11" dependencies = [ "dirs", ] [[package]] name = "alvr_graphics" -version = "21.0.0-dev10" +version = "21.0.0-dev11" dependencies = [ "alvr_common", "alvr_session", @@ -339,7 +339,7 @@ dependencies = [ [[package]] name = "alvr_gui_common" -version = "21.0.0-dev10" +version = "21.0.0-dev11" dependencies = [ "alvr_common", "egui", @@ -347,7 +347,7 @@ dependencies = [ [[package]] name = "alvr_launcher" -version = "21.0.0-dev10" +version = "21.0.0-dev11" dependencies = [ "alvr_adb", "alvr_common", @@ -370,7 +370,7 @@ dependencies = [ [[package]] name = "alvr_packets" -version = "21.0.0-dev10" +version = "21.0.0-dev11" dependencies = [ "alvr_common", "alvr_session", @@ -380,7 +380,7 @@ dependencies = [ [[package]] name = "alvr_server_core" -version = "21.0.0-dev10" +version = "21.0.0-dev11" dependencies = [ "alvr_adb", "alvr_audio", @@ -409,7 +409,7 @@ dependencies = [ [[package]] name = "alvr_server_io" -version = "21.0.0-dev10" +version = "21.0.0-dev11" dependencies = [ "alvr_common", "alvr_events", @@ -424,7 +424,7 @@ dependencies = [ [[package]] name = "alvr_server_openvr" -version = "21.0.0-dev10" +version = "21.0.0-dev11" dependencies = [ "alvr_common", "alvr_filesystem", @@ -442,7 +442,7 @@ dependencies = [ [[package]] name = "alvr_session" -version = "21.0.0-dev10" +version = "21.0.0-dev11" dependencies = [ "alvr_common", "alvr_filesystem", @@ -456,7 +456,7 @@ dependencies = [ [[package]] name = "alvr_sockets" -version = "21.0.0-dev10" +version = "21.0.0-dev11" dependencies = [ "alvr_common", "alvr_session", @@ -469,7 +469,7 @@ dependencies = [ [[package]] name = "alvr_system_info" -version = "21.0.0-dev10" +version = "21.0.0-dev11" dependencies = [ "alvr_common", "jni", @@ -483,7 +483,7 @@ dependencies = [ [[package]] name = "alvr_vrcompositor_wrapper" -version = "21.0.0-dev10" +version = "21.0.0-dev11" dependencies = [ "alvr_common", "alvr_filesystem", @@ -493,7 +493,7 @@ dependencies = [ [[package]] name = "alvr_vulkan_layer" -version = "21.0.0-dev10" +version = "21.0.0-dev11" dependencies = [ "alvr_common", "alvr_filesystem", @@ -505,7 +505,7 @@ dependencies = [ [[package]] name = "alvr_xtask" -version = "21.0.0-dev10" +version = "21.0.0-dev11" dependencies = [ "alvr_filesystem", "pico-args", diff --git a/Cargo.toml b/Cargo.toml index 0bc21b26df..904e4c25a2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ resolver = "2" members = ["alvr/*"] [workspace.package] -version = "21.0.0-dev10" +version = "21.0.0-dev11" edition = "2024" rust-version = "1.88" authors = ["alvr-org"] diff --git a/alvr/client_core/src/lib.rs b/alvr/client_core/src/lib.rs index 9747c1fac2..980ee5600d 100644 --- a/alvr/client_core/src/lib.rs +++ b/alvr/client_core/src/lib.rs @@ -222,6 +222,14 @@ impl ClientCoreContext { } } + pub fn send_proximity_state(&self, headset_is_worn: bool) { + if let Some(sender) = &mut *self.connection_context.control_sender.lock() { + sender + .send(&ClientControlPacket::ProximityState(headset_is_worn)) + .ok(); + } + } + pub fn get_total_prediction_offset(&self) -> Duration { dbg_client_core!("get_total_prediction_offset"); diff --git a/alvr/client_openxr/src/lib.rs b/alvr/client_openxr/src/lib.rs index e49c7cee8a..4f5da4fd0d 100644 --- a/alvr/client_openxr/src/lib.rs +++ b/alvr/client_openxr/src/lib.rs @@ -166,6 +166,7 @@ pub fn entry_point() { exts.ext_eye_gaze_interaction = available_extensions.ext_eye_gaze_interaction; exts.ext_hand_tracking = available_extensions.ext_hand_tracking; exts.ext_local_floor = available_extensions.ext_local_floor; + exts.ext_user_presence = available_extensions.ext_user_presence; exts.fb_body_tracking = available_extensions.fb_body_tracking; exts.fb_color_space = available_extensions.fb_color_space; exts.fb_composition_layer_settings = available_extensions.fb_composition_layer_settings; @@ -320,6 +321,7 @@ pub fn entry_point() { let mut passthrough_layer = None; let mut event_storage = xr::EventDataBuffer::new(); + let mut headset_is_worn = true; 'render_loop: loop { while let Some(event) = xr_instance.poll_event(&mut event_storage).unwrap() { match event { @@ -378,6 +380,12 @@ pub fn entry_point() { | xr::Event::PassthroughStateChangedFB(_) => { // todo } + xr::Event::UserPresenceChangedEXT(event) => { + alvr_common::info!("user present: {:?}", event.is_user_present()); + headset_is_worn = event.is_user_present(); + + core_context.send_proximity_state(event.is_user_present()); + } _ => (), } } @@ -410,6 +418,8 @@ pub fn entry_point() { } stream_context = Some(context); + + core_context.send_proximity_state(headset_is_worn); } ClientCoreEvent::StreamingStopped => { if passthrough_layer.is_none() { diff --git a/alvr/packets/src/lib.rs b/alvr/packets/src/lib.rs index e3f4537830..8f6725a701 100644 --- a/alvr/packets/src/lib.rs +++ b/alvr/packets/src/lib.rs @@ -193,6 +193,7 @@ pub enum ClientControlPacket { level: LogSeverity, message: String, }, + ProximityState(bool), Reserved(String), ReservedBuffer(Vec), } diff --git a/alvr/server_core/src/c_api.rs b/alvr/server_core/src/c_api.rs index 32e2948a21..657937d57d 100644 --- a/alvr/server_core/src/c_api.rs +++ b/alvr/server_core/src/c_api.rs @@ -71,6 +71,7 @@ pub enum AlvrEvent { CaptureFrame, RestartPending, ShutdownPending, + ProximityState(bool), } #[repr(C)] @@ -293,6 +294,9 @@ pub unsafe extern "C" fn alvr_poll_event(out_event: *mut AlvrEvent, timeout_ns: }, ServerCoreEvent::GameRenderLatencyFeedback(_) | ServerCoreEvent::SetOpenvrProperty { .. } => {} // implementation not needed + ServerCoreEvent::ProximityState(headset_is_worn) => unsafe { + *out_event = AlvrEvent::ProximityState(headset_is_worn); + }, } true diff --git a/alvr/server_core/src/connection.rs b/alvr/server_core/src/connection.rs index 0ff4c173ad..a8add4d029 100644 --- a/alvr/server_core/src/connection.rs +++ b/alvr/server_core/src/connection.rs @@ -1277,6 +1277,11 @@ fn connection_pipeline( info!("Client {client_hostname}: [{level:?}] {message}") } ClientControlPacket::KeepAlive | ClientControlPacket::StreamReady => (), + ClientControlPacket::ProximityState(headset_is_worn) => { + ctx.events_sender + .send(ServerCoreEvent::ProximityState(headset_is_worn)) + .ok(); + } ClientControlPacket::Reserved(_) | ClientControlPacket::ReservedBuffer(_) => (), } diff --git a/alvr/server_core/src/lib.rs b/alvr/server_core/src/lib.rs index 47d6295332..b3f180423f 100644 --- a/alvr/server_core/src/lib.rs +++ b/alvr/server_core/src/lib.rs @@ -89,6 +89,7 @@ pub enum ServerCoreEvent { GameRenderLatencyFeedback(Duration), // only used for SteamVR ShutdownPending, RestartPending, + ProximityState(bool), } pub struct ConnectionContext { diff --git a/alvr/server_openvr/cpp/alvr_server/HMD.cpp b/alvr/server_openvr/cpp/alvr_server/HMD.cpp index 27c41db105..cdf48f8aff 100644 --- a/alvr/server_openvr/cpp/alvr_server/HMD.cpp +++ b/alvr/server_openvr/cpp/alvr_server/HMD.cpp @@ -296,6 +296,10 @@ void Hmd::SetViewParams(const FfiViewParams params[2]) { ); } +void Hmd::SetProximityState(bool headsetIsWorn) { + vr::VRDriverInput()->UpdateBooleanComponent(m_proximity, headsetIsWorn, 0.0); +} + void Hmd::GetWindowBounds(int32_t* pnX, int32_t* pnY, uint32_t* pnWidth, uint32_t* pnHeight) { Debug( "Hmd::GetWindowBounds %dx%d - %dx%d\n", diff --git a/alvr/server_openvr/cpp/alvr_server/HMD.h b/alvr/server_openvr/cpp/alvr_server/HMD.h index 91077767bb..661f6a4df3 100644 --- a/alvr/server_openvr/cpp/alvr_server/HMD.h +++ b/alvr/server_openvr/cpp/alvr_server/HMD.h @@ -29,6 +29,7 @@ class Hmd : public TrackedDevice, vr::IVRDisplayComponent { void StartStreaming(); void StopStreaming(); void SetViewParams(const FfiViewParams params[2]); + void SetProximityState(bool headsetIsWorn); private: vr::VRInputComponentHandle_t m_proximity; diff --git a/alvr/server_openvr/cpp/alvr_server/alvr_server.cpp b/alvr/server_openvr/cpp/alvr_server/alvr_server.cpp index 5ad783168b..2a91897dc0 100644 --- a/alvr/server_openvr/cpp/alvr_server/alvr_server.cpp +++ b/alvr/server_openvr/cpp/alvr_server/alvr_server.cpp @@ -512,6 +512,12 @@ void SetButton(unsigned long long buttonID, FfiButtonValue value) { } } +void SetProximityState(bool headset_is_worn) { + if (g_driver_provider.hmd) { + g_driver_provider.hmd->SetProximityState(headset_is_worn); + } +} + void SetChaperoneArea(float areaWidth, float areaHeight) { _SetChaperoneArea(areaWidth, areaHeight); } diff --git a/alvr/server_openvr/cpp/alvr_server/bindings.h b/alvr/server_openvr/cpp/alvr_server/bindings.h index 1e9101c8b1..850aaf89f5 100644 --- a/alvr/server_openvr/cpp/alvr_server/bindings.h +++ b/alvr/server_openvr/cpp/alvr_server/bindings.h @@ -161,6 +161,7 @@ extern "C" void RegisterButton(void* instancePtr, unsigned long long buttonID); extern "C" void SetLocalViewParams(const FfiViewParams params[2]); extern "C" void SetBattery(unsigned long long deviceID, float gauge_value, bool is_plugged); extern "C" void SetButton(unsigned long long buttonID, FfiButtonValue value); +extern "C" void SetProximityState(bool headset_is_worn); extern "C" void InitOpenvrClient(); extern "C" void ShutdownOpenvrClient(); diff --git a/alvr/server_openvr/src/lib.rs b/alvr/server_openvr/src/lib.rs index 8c3a926129..c334500358 100644 --- a/alvr/server_openvr/src/lib.rs +++ b/alvr/server_openvr/src/lib.rs @@ -293,6 +293,9 @@ fn event_loop(events_receiver: mpsc::Receiver) { unsafe { ShutdownSteamvr() }; } + ServerCoreEvent::ProximityState(headset_is_worn) => unsafe { + SetProximityState(headset_is_worn) + }, } }