diff --git a/crates/bevy_openxr/examples/3d_scene.rs b/crates/bevy_openxr/examples/3d_scene.rs index 3b6237e..8d291da 100644 --- a/crates/bevy_openxr/examples/3d_scene.rs +++ b/crates/bevy_openxr/examples/3d_scene.rs @@ -13,10 +13,11 @@ fn main() -> AppExit { DefaultPlugins.build().disable::(), )) .insert_resource(OxrSessionConfig { - blend_modes: Some(vec![ + blend_mode_preference: vec![ EnvironmentBlendMode::ALPHA_BLEND, + EnvironmentBlendMode::ADDITIVE, EnvironmentBlendMode::OPAQUE, - ]), + ], ..default() }) .add_plugins(bevy_mod_xr::hand_debug_gizmos::HandGizmosPlugin) diff --git a/crates/bevy_openxr/examples/android/Cargo.toml b/crates/bevy_openxr/examples/android/Cargo.toml index 3663aec..aadfe5a 100644 --- a/crates/bevy_openxr/examples/android/Cargo.toml +++ b/crates/bevy_openxr/examples/android/Cargo.toml @@ -92,6 +92,6 @@ categories = [ # https://developer.android.com/studio/publish/app-signing # # !! IMPORTANT !! -[package.metadata.android.signing.release] -path = "./hotham_examples.keystore" -keystore_password = "chomsky-vigilant-spa" +# [package.metadata.android.signing.release] +# path = "./hotham_examples.keystore" +# keystore_password = "chomsky-vigilant-spa" diff --git a/crates/bevy_openxr/examples/android/hotham_examples.keystore b/crates/bevy_openxr/examples/android/hotham_examples.keystore deleted file mode 100644 index 62623c4..0000000 Binary files a/crates/bevy_openxr/examples/android/hotham_examples.keystore and /dev/null differ diff --git a/crates/bevy_openxr/examples/android/src/lib.rs b/crates/bevy_openxr/examples/android/src/lib.rs index 66b212b..690ef68 100644 --- a/crates/bevy_openxr/examples/android/src/lib.rs +++ b/crates/bevy_openxr/examples/android/src/lib.rs @@ -16,6 +16,7 @@ fn main() { ..default() })) .add_plugins(bevy_mod_xr::hand_debug_gizmos::HandGizmosPlugin) + .add_plugins(bevy_mod_openxr::features::fb_passthrough::OxrFbPassthroughPlugin) .add_systems(Startup, setup) .add_systems(Update, modify_msaa) .insert_resource(AmbientLight { diff --git a/crates/bevy_openxr/examples/overlay.rs b/crates/bevy_openxr/examples/overlay.rs index 9c1bf2f..263e902 100644 --- a/crates/bevy_openxr/examples/overlay.rs +++ b/crates/bevy_openxr/examples/overlay.rs @@ -19,12 +19,13 @@ fn main() { ..OxrInitPlugin::default() })) .insert_resource(OxrSessionConfig { - blend_modes: Some({ + blend_mode_preference: { vec![ EnvironmentBlendMode::ALPHA_BLEND, + EnvironmentBlendMode::ADDITIVE, EnvironmentBlendMode::OPAQUE, ] - }), + }, ..OxrSessionConfig::default() }) .insert_resource(ClearColor(Color::NONE)) diff --git a/crates/bevy_openxr/src/openxr/environment_blend_mode.rs b/crates/bevy_openxr/src/openxr/environment_blend_mode.rs new file mode 100644 index 0000000..7fcc822 --- /dev/null +++ b/crates/bevy_openxr/src/openxr/environment_blend_mode.rs @@ -0,0 +1,39 @@ +use bevy::{ecs::resource::Resource, render::extract_resource::ExtractResource}; +use openxr::EnvironmentBlendMode; + +#[derive(Resource, ExtractResource, Clone)] +pub struct OxrEnvironmentBlendModes { + available_blend_modes: Vec, + current_blend_mode: EnvironmentBlendMode, +} + +impl OxrEnvironmentBlendModes { + pub(crate) fn new( + available_modes: Vec, + preferences: &[EnvironmentBlendMode], + ) -> Option { + let blend_mode = preferences.iter().find(|m| available_modes.contains(m))?; + + Some(Self { + available_blend_modes: available_modes, + current_blend_mode: *blend_mode, + }) + } + + /// returns whether the blend_mode was changed + pub fn set_blend_mode(&mut self, blend_mode: EnvironmentBlendMode) -> bool { + if self.available_blend_modes.contains(&blend_mode) { + self.current_blend_mode = blend_mode; + return true; + } + false + } + + pub fn blend_mode(&self) -> EnvironmentBlendMode { + self.current_blend_mode + } + + pub fn available_blend_modes(&self) -> &[EnvironmentBlendMode] { + &self.available_blend_modes + } +} diff --git a/crates/bevy_openxr/src/openxr/features/passthrough.rs b/crates/bevy_openxr/src/openxr/features/fb_passthrough.rs similarity index 90% rename from crates/bevy_openxr/src/openxr/features/passthrough.rs rename to crates/bevy_openxr/src/openxr/features/fb_passthrough.rs index 1993fe5..5eddf00 100644 --- a/crates/bevy_openxr/src/openxr/features/passthrough.rs +++ b/crates/bevy_openxr/src/openxr/features/fb_passthrough.rs @@ -11,9 +11,9 @@ use crate::resources::*; use crate::session::OxrSession; use crate::types::Result as OxrResult; -pub struct OxrPassthroughPlugin; +pub struct OxrFbPassthroughPlugin; -impl Plugin for OxrPassthroughPlugin { +impl Plugin for OxrFbPassthroughPlugin { fn build(&self, app: &mut App) { if app .world() @@ -94,12 +94,12 @@ pub fn supports_passthrough(instance: &OxrInstance, system: OxrSystemId) -> OxrR return Ok(false); } unsafe { - let mut hand = openxr::sys::SystemPassthroughProperties2FB { + let mut properties = openxr::sys::SystemPassthroughProperties2FB { ty: SystemPassthroughProperties2FB::TYPE, next: std::ptr::null(), capabilities: PassthroughCapabilityFlagsFB::PASSTHROUGH_CAPABILITY, }; - let mut p = openxr::sys::SystemProperties::out(&mut hand as *mut _ as _); + let mut p = openxr::sys::SystemProperties::out(&mut properties as *mut _ as _); cvt((instance.fp().get_system_properties)( instance.as_raw(), system.0, @@ -107,10 +107,10 @@ pub fn supports_passthrough(instance: &OxrInstance, system: OxrSystemId) -> OxrR ))?; bevy::log::info!( "From supports_passthrough: Passthrough capabilities: {:?}", - hand.capabilities + properties.capabilities ); Ok( - (hand.capabilities & PassthroughCapabilityFlagsFB::PASSTHROUGH_CAPABILITY) + (properties.capabilities & PassthroughCapabilityFlagsFB::PASSTHROUGH_CAPABILITY) == PassthroughCapabilityFlagsFB::PASSTHROUGH_CAPABILITY, ) } diff --git a/crates/bevy_openxr/src/openxr/features/mod.rs b/crates/bevy_openxr/src/openxr/features/mod.rs index b5d55e3..d7a1da6 100644 --- a/crates/bevy_openxr/src/openxr/features/mod.rs +++ b/crates/bevy_openxr/src/openxr/features/mod.rs @@ -1,4 +1,4 @@ pub mod handtracking; #[cfg(feature = "passthrough")] -pub mod passthrough; +pub mod fb_passthrough; pub mod overlay; diff --git a/crates/bevy_openxr/src/openxr/init.rs b/crates/bevy_openxr/src/openxr/init.rs index b5a9ed5..8e2aca1 100644 --- a/crates/bevy_openxr/src/openxr/init.rs +++ b/crates/bevy_openxr/src/openxr/init.rs @@ -28,6 +28,7 @@ use crate::session::OxrSessionCreateNextChain; use crate::types::Result as OxrResult; use crate::types::*; +use super::environment_blend_mode::OxrEnvironmentBlendModes; use super::exts::OxrEnabledExtensions; use super::poll_events::OxrEventHandlerExt; use super::poll_events::OxrEventIn; @@ -66,7 +67,6 @@ impl Default for OxrInitPlugin { app_info: default(), exts: { let mut exts = OxrExtensions::default(); - exts.enable_fb_passthrough(); exts.enable_hand_tracking(); exts }, @@ -104,6 +104,7 @@ impl Plugin for OxrInitPlugin { debug_flags: self.render_debug_flags, }, ExtractResourcePlugin::::default(), + ExtractResourcePlugin::::default(), )) .add_oxr_event_handler(handle_events) .add_systems( @@ -249,7 +250,7 @@ impl OxrInitPlugin { // check available extensions and send a warning for any wanted extensions that aren't available. for ext in available_exts.unavailable_exts(&self.exts) { - error!( + warn!( "Extension \"{ext}\" not available in the current OpenXR runtime. Disabling extension." ); } @@ -273,13 +274,7 @@ impl OxrInitPlugin { let exts = self.exts.clone() & available_exts; - let instance = entry.create_instance( - self.app_info.clone(), - exts.clone(), - // &["XR_APILAYER_LUNARG_api_dump"], - &[], - backend, - )?; + let instance = entry.create_instance(self.app_info.clone(), exts.clone(), &[], backend)?; let instance_props = instance.properties()?; info!( @@ -362,7 +357,7 @@ fn init_xr_session( system_id: openxr::SystemId, chain: &mut OxrSessionCreateNextChain, OxrSessionConfig { - blend_modes, + blend_mode_preference, formats, resolutions, }: OxrSessionConfig, @@ -374,6 +369,7 @@ fn init_xr_session( OxrSwapchain, OxrSwapchainImages, OxrCurrentSessionConfig, + OxrEnvironmentBlendModes, )> { let (session, frame_waiter, frame_stream) = unsafe { instance.create_session(system_id, graphics_info, chain)? }; @@ -461,25 +457,10 @@ fn init_xr_session( instance.enumerate_environment_blend_modes(system_id, view_configuration_type)?; // blend mode selection - let blend_mode = if let Some(wanted_blend_modes) = &blend_modes { - let mut blend_mode = None; - for wanted_blend_mode in wanted_blend_modes { - if available_blend_modes.contains(wanted_blend_mode) { - blend_mode = Some(*wanted_blend_mode); - break; - } - } - blend_mode - } else { - available_blend_modes.first().copied() - } - .ok_or(OxrError::NoAvailableBlendMode)?; + let blend_modes = OxrEnvironmentBlendModes::new(available_blend_modes, &blend_mode_preference) + .ok_or(OxrError::NoAvailableBlendMode)?; - let graphics_info = OxrCurrentSessionConfig { - blend_mode, - resolution, - format, - }; + let graphics_info = OxrCurrentSessionConfig { resolution, format }; Ok(( session, @@ -488,6 +469,7 @@ fn init_xr_session( swapchain, images, graphics_info, + blend_modes, )) } @@ -508,7 +490,15 @@ pub fn create_xr_session(world: &mut World) { session_config.clone(), session_create_info.clone(), ) { - Ok((session, frame_waiter, frame_stream, swapchain, images, graphics_info)) => { + Ok(( + session, + frame_waiter, + frame_stream, + swapchain, + images, + graphics_info, + blend_modes, + )) => { world.insert_resource(session.clone()); world.insert_resource(frame_waiter); world.insert_resource(images); @@ -524,6 +514,7 @@ pub fn create_xr_session(world: &mut World) { .expect("added by xr session plugin") .clone(), }); + world.insert_resource(blend_modes); } Err(e) => error!("Failed to initialize XrSession: {e}"), } diff --git a/crates/bevy_openxr/src/openxr/mod.rs b/crates/bevy_openxr/src/openxr/mod.rs index 989f30d..dc23337 100644 --- a/crates/bevy_openxr/src/openxr/mod.rs +++ b/crates/bevy_openxr/src/openxr/mod.rs @@ -14,14 +14,12 @@ use render::OxrRenderPlugin; use resources::OxrInstance; use session::OxrSession; -use self::{ - features::{handtracking::HandTrackingPlugin, passthrough::OxrPassthroughPlugin}, - reference_space::OxrReferenceSpacePlugin, -}; +use self::{features::handtracking::HandTrackingPlugin, reference_space::OxrReferenceSpacePlugin}; pub mod action_binding; pub mod action_set_attaching; pub mod action_set_syncing; +pub mod environment_blend_mode; pub mod error; pub mod exts; pub mod features; @@ -59,13 +57,11 @@ pub fn add_xr_plugins(plugins: G) -> PluginGroupBuilder { plugins .build() .disable::() - // .disable::() .add_before::(XrSessionPlugin { auto_handle: true }) .add_before::(OxrInitPlugin::default()) .add(OxrEventsPlugin) .add(OxrReferenceSpacePlugin::default()) .add(OxrRenderPlugin::default()) - .add(OxrPassthroughPlugin) .add(HandTrackingPlugin::default()) .add(XrCameraPlugin) .add(action_set_attaching::OxrActionAttachingPlugin) @@ -74,20 +70,14 @@ pub fn add_xr_plugins(plugins: G) -> PluginGroupBuilder { .add(features::overlay::OxrOverlayPlugin) .add(spaces::OxrSpatialPlugin) .add(spaces::OxrSpacePatchingPlugin) - // .add(XrActionPlugin) // we should probably handle the exiting ourselfs so that we can correctly end the // session and instance .set(WindowPlugin { primary_window: Some(Window { transparent: true, present_mode: PresentMode::AutoNoVsync, - // title: self.app_info.name.clone(), ..default() }), - // #[cfg(target_os = "android")] - // exit_condition: bevy::window::ExitCondition::DontExit, - #[cfg(target_os = "android")] - close_when_requested: true, ..default() }) } diff --git a/crates/bevy_openxr/src/openxr/render.rs b/crates/bevy_openxr/src/openxr/render.rs index 1e5af76..1f6eed1 100644 --- a/crates/bevy_openxr/src/openxr/render.rs +++ b/crates/bevy_openxr/src/openxr/render.rs @@ -22,6 +22,8 @@ use openxr::ViewStateFlags; use crate::{init::should_run_frame_loop, resources::*}; use crate::{layer_builder::ProjectionLayer, session::OxrSession}; +use super::environment_blend_mode::OxrEnvironmentBlendModes; + #[derive(Debug, Hash, PartialEq, Eq, Clone, Copy, SystemSet)] pub struct OxrRenderBegin; @@ -393,7 +395,7 @@ pub fn end_frame(world: &mut World) { let _span = debug_span!("xr_end_frame").entered(); if let Err(e) = frame_stream.end( frame_state.predicted_display_time, - world.resource::().blend_mode, + world.resource::().blend_mode(), &layers, ) { error!("Failed to end frame stream: {e}"); diff --git a/crates/bevy_openxr/src/openxr/resources.rs b/crates/bevy_openxr/src/openxr/resources.rs index 58fce9c..c98e041 100644 --- a/crates/bevy_openxr/src/openxr/resources.rs +++ b/crates/bevy_openxr/src/openxr/resources.rs @@ -332,7 +332,6 @@ pub struct OxrRenderLayers(pub Vec>); /// Resource storing graphics info for the currently running session. #[derive(Clone, Copy, Resource, ExtractResource)] pub struct OxrCurrentSessionConfig { - pub blend_mode: EnvironmentBlendMode, pub resolution: UVec2, pub format: wgpu::TextureFormat, } @@ -341,7 +340,7 @@ pub struct OxrCurrentSessionConfig { /// This is used to store information from startup that is needed to create the session after the instance has been created. pub struct OxrSessionConfig { /// List of blend modes the openxr session can use. If [None], pick the first available blend mode. - pub blend_modes: Option>, + pub blend_mode_preference: Vec, /// List of formats the openxr session can use. If [None], pick the first available format pub formats: Option>, /// List of resolutions that the openxr swapchain can use. If [None] pick the first available resolution. @@ -350,7 +349,7 @@ pub struct OxrSessionConfig { impl Default for OxrSessionConfig { fn default() -> Self { Self { - blend_modes: Some(vec![openxr::EnvironmentBlendMode::OPAQUE]), + blend_mode_preference: vec![openxr::EnvironmentBlendMode::OPAQUE], formats: Some(vec![wgpu::TextureFormat::Rgba8UnormSrgb]), resolutions: default(), } diff --git a/crates/bevy_xr/src/session.rs b/crates/bevy_xr/src/session.rs index 5506a3b..8273619 100644 --- a/crates/bevy_xr/src/session.rs +++ b/crates/bevy_xr/src/session.rs @@ -191,7 +191,7 @@ impl Plugin for XrSessionPlugin { render_app .init_schedule(XrPreDestroySession) - .init_resource::() + // .init_resource::() .configure_sets( Render, (XrRenderSet::HandleEvents, XrRenderSet::PreRender).chain(),