use bevy_app::{App, Plugin}; use bevy_ecs::{ entity::Entity, query::With, resource::Resource, system::{Commands, Query, Res}, }; use bevy_log::error; use bevy_math::Isometry3d; use bevy_mod_xr::{ session::{XrPreDestroySession, XrSessionCreated}, spaces::{XrPrimaryReferenceSpace, XrReferenceSpace}, }; use bevy_render::{RenderApp, extract_resource::ExtractResourcePlugin}; use crate::session::OxrSession; pub struct OxrReferenceSpacePlugin { pub default_primary_ref_space: openxr::ReferenceSpaceType, } impl Default for OxrReferenceSpacePlugin { fn default() -> Self { Self { default_primary_ref_space: openxr::ReferenceSpaceType::STAGE, } } } /// Resource specifying what the type should used be for the [`XrPrimaryReferenceSpace`]. Set through [`OxrReferenceSpacePlugin`]. #[derive(Resource)] struct OxrDefaultPrimaryReferenceSpaceType(openxr::ReferenceSpaceType); impl Plugin for OxrReferenceSpacePlugin { fn build(&self, app: &mut App) { app.add_plugins(ExtractResourcePlugin::::default()) .insert_resource(OxrDefaultPrimaryReferenceSpaceType( self.default_primary_ref_space, )) .add_systems(XrSessionCreated, set_primary_ref_space) .add_systems(XrPreDestroySession, cleanup); let render_app = app.sub_app_mut(RenderApp); render_app.add_systems(XrPreDestroySession, cleanup); } } fn cleanup(query: Query>, mut cmds: Commands) { cmds.remove_resource::(); for e in &query { cmds.entity(e).remove::(); } } fn set_primary_ref_space( session: Res, space_type: Res, mut cmds: Commands, ) { match session.create_reference_space(space_type.0, Isometry3d::IDENTITY) { Ok(space) => { cmds.insert_resource(XrPrimaryReferenceSpace(space)); } Err(openxr::sys::Result::ERROR_EXTENSION_NOT_PRESENT) => { error!("Required Extension for Reference Space not loaded"); } Err(err) => error!("Error while creating reference space: {}", err.to_string()), }; }