Merge pull request #126 from Schmarni-Dev/oxr_overlays_attempt_2
Add EXTX_overlay support, but better and more complete
This commit is contained in:
95
crates/bevy_openxr/examples/overlay.rs
Normal file
95
crates/bevy_openxr/examples/overlay.rs
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
//! A simple 3D scene with light shining over a cube sitting on a plane.
|
||||||
|
|
||||||
|
use bevy::prelude::*;
|
||||||
|
use bevy_openxr::{add_xr_plugins, init::OxrInitPlugin, types::OxrExtensions};
|
||||||
|
use bevy_xr::session::XrStatus;
|
||||||
|
use openxr::EnvironmentBlendMode;
|
||||||
|
use wgpu::TextureFormat;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
App::new()
|
||||||
|
.add_plugins(add_xr_plugins(DefaultPlugins).build().set(OxrInitPlugin {
|
||||||
|
exts: {
|
||||||
|
let mut exts = OxrExtensions::default();
|
||||||
|
exts.enable_hand_tracking();
|
||||||
|
exts.other.push("XR_EXTX_overlay\0".into());
|
||||||
|
exts
|
||||||
|
},
|
||||||
|
// blend_modes: Some({
|
||||||
|
// let mut v = Vec::new();
|
||||||
|
// v.push(EnvironmentBlendMode::ALPHA_BLEND);
|
||||||
|
// v.push(EnvironmentBlendMode::ADDITIVE);
|
||||||
|
// v.push(EnvironmentBlendMode::OPAQUE);
|
||||||
|
// v
|
||||||
|
// }),
|
||||||
|
// formats: Some({
|
||||||
|
// let mut v = Vec::new();
|
||||||
|
// // v.push(TextureFormat::Rgba8Uint);
|
||||||
|
// v.push(TextureFormat::Rgba8Unorm);
|
||||||
|
// v.push(TextureFormat::Rgba8UnormSrgb);
|
||||||
|
// v
|
||||||
|
// }),
|
||||||
|
..OxrInitPlugin::default()
|
||||||
|
}))
|
||||||
|
.insert_resource(ClearColor(Color::NONE))
|
||||||
|
.add_plugins(bevy_xr_utils::hand_gizmos::HandGizmosPlugin)
|
||||||
|
.add_systems(Startup, setup)
|
||||||
|
.add_systems(Update, handle_input)
|
||||||
|
.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_input(
|
||||||
|
keys: Res<ButtonInput<KeyCode>>,
|
||||||
|
mut end: EventWriter<bevy_xr::session::EndXrSession>,
|
||||||
|
mut _destroy: EventWriter<bevy_xr::session::DestroyXrSession>,
|
||||||
|
mut _begin: EventWriter<bevy_xr::session::BeginXrSession>,
|
||||||
|
mut create: EventWriter<bevy_xr::session::CreateXrSession>,
|
||||||
|
state: Res<XrStatus>,
|
||||||
|
) {
|
||||||
|
if keys.just_pressed(KeyCode::KeyE) {
|
||||||
|
info!("sending end");
|
||||||
|
end.send_default();
|
||||||
|
}
|
||||||
|
if keys.just_pressed(KeyCode::KeyC) {
|
||||||
|
info!("sending create");
|
||||||
|
create.send_default();
|
||||||
|
}
|
||||||
|
if keys.just_pressed(KeyCode::KeyI) {
|
||||||
|
info!("current state: {:?}", *state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// set up a simple 3D scene
|
||||||
|
fn setup(
|
||||||
|
mut commands: Commands,
|
||||||
|
mut meshes: ResMut<Assets<Mesh>>,
|
||||||
|
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||||
|
) {
|
||||||
|
// circular base
|
||||||
|
// commands.spawn(PbrBundle {
|
||||||
|
// mesh: meshes.add(Circle::new(4.0)),
|
||||||
|
// material: materials.add(Color::WHITE),
|
||||||
|
// transform: Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)),
|
||||||
|
// ..default()
|
||||||
|
// });
|
||||||
|
// cube
|
||||||
|
commands.spawn(PbrBundle {
|
||||||
|
mesh: meshes.add(Cuboid::new(1.0, 1.0, 1.0)),
|
||||||
|
material: materials.add(Color::rgb_u8(124, 144, 255)),
|
||||||
|
transform: Transform::from_xyz(0.0, 2.5, 0.0),
|
||||||
|
..default()
|
||||||
|
});
|
||||||
|
// light
|
||||||
|
commands.spawn(PointLightBundle {
|
||||||
|
point_light: PointLight {
|
||||||
|
shadows_enabled: true,
|
||||||
|
..default()
|
||||||
|
},
|
||||||
|
transform: Transform::from_xyz(4.0, 8.0, 4.0),
|
||||||
|
..default()
|
||||||
|
});
|
||||||
|
commands.spawn(Camera3dBundle {
|
||||||
|
transform: Transform::from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y),
|
||||||
|
..default()
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -1,6 +1,9 @@
|
|||||||
use bevy::prelude::{Deref, DerefMut};
|
use bevy::{ecs::system::Resource, prelude::{Deref, DerefMut}};
|
||||||
use openxr::ExtensionSet;
|
use openxr::ExtensionSet;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq, Deref, DerefMut, Resource)]
|
||||||
|
pub struct OxrEnabledExtensions(pub OxrExtensions);
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, Deref, DerefMut)]
|
#[derive(Clone, Debug, Eq, PartialEq, Deref, DerefMut)]
|
||||||
pub struct OxrExtensions(ExtensionSet);
|
pub struct OxrExtensions(ExtensionSet);
|
||||||
impl OxrExtensions {
|
impl OxrExtensions {
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
pub mod handtracking;
|
pub mod handtracking;
|
||||||
#[cfg(feature = "passthrough")]
|
#[cfg(feature = "passthrough")]
|
||||||
pub mod passthrough;
|
pub mod passthrough;
|
||||||
|
pub mod overlay;
|
||||||
|
|||||||
95
crates/bevy_openxr/src/openxr/features/overlay.rs
Normal file
95
crates/bevy_openxr/src/openxr/features/overlay.rs
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
use std::{mem, ptr};
|
||||||
|
|
||||||
|
use bevy::prelude::*;
|
||||||
|
use openxr::sys;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
next_chain::{OxrNextChainStructBase, OxrNextChainStructProvider},
|
||||||
|
openxr::exts::OxrEnabledExtensions,
|
||||||
|
session::{OxrSessionCreateNextChain, OxrSessionCreateNextProvider},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct OxrOverlayPlugin;
|
||||||
|
|
||||||
|
impl Plugin for OxrOverlayPlugin {
|
||||||
|
fn build(&self, app: &mut bevy::prelude::App) {
|
||||||
|
app.add_event::<OxrOverlaySessionEvent>();
|
||||||
|
app.init_resource::<OxrOverlaySettings>();
|
||||||
|
app.add_systems(First, add_overlay_info_to_chain);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Resource)]
|
||||||
|
pub struct OxrOverlaySettings {
|
||||||
|
pub session_layer_placement: u32,
|
||||||
|
pub flags: openxr::OverlaySessionCreateFlagsEXTX,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for OxrOverlaySettings {
|
||||||
|
fn default() -> Self {
|
||||||
|
OxrOverlaySettings {
|
||||||
|
session_layer_placement: 0,
|
||||||
|
flags: openxr::OverlaySessionCreateFlagsEXTX::EMPTY,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_overlay_info_to_chain(
|
||||||
|
mut chain: NonSendMut<OxrSessionCreateNextChain>,
|
||||||
|
exts: Res<OxrEnabledExtensions>,
|
||||||
|
settings: Res<OxrOverlaySettings>,
|
||||||
|
) {
|
||||||
|
if exts.other.contains(&"XR_EXTX_overlay\0".to_string()) {
|
||||||
|
chain.push(OxrSessionCreateInfoOverlay::new(
|
||||||
|
settings.flags,
|
||||||
|
settings.session_layer_placement,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Event, Clone, Copy, Debug)]
|
||||||
|
pub enum OxrOverlaySessionEvent {
|
||||||
|
MainSessionVisibilityChanged {
|
||||||
|
visible: bool,
|
||||||
|
flags: openxr::OverlayMainSessionFlagsEXTX,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct OxrSessionCreateInfoOverlay {
|
||||||
|
inner: sys::SessionCreateInfoOverlayEXTX,
|
||||||
|
}
|
||||||
|
impl OxrSessionCreateInfoOverlay {
|
||||||
|
pub const fn new(
|
||||||
|
flags: openxr::OverlaySessionCreateFlagsEXTX,
|
||||||
|
session_layers_placement: u32,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
inner: sys::SessionCreateInfoOverlayEXTX {
|
||||||
|
ty: sys::SessionCreateInfoOverlayEXTX::TYPE,
|
||||||
|
next: ptr::null(),
|
||||||
|
create_flags: flags,
|
||||||
|
session_layers_placement,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Default for OxrSessionCreateInfoOverlay {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new(openxr::OverlaySessionCreateFlagsEXTX::EMPTY, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OxrNextChainStructProvider for OxrSessionCreateInfoOverlay {
|
||||||
|
fn header(&self) -> &OxrNextChainStructBase {
|
||||||
|
unsafe { mem::transmute(&self.inner) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_next(&mut self, next: &OxrNextChainStructBase) {
|
||||||
|
self.inner.next = next as *const _ as *const _;
|
||||||
|
}
|
||||||
|
fn clear_next(&mut self) {
|
||||||
|
self.inner.next = ptr::null();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OxrSessionCreateNextProvider for OxrSessionCreateInfoOverlay {}
|
||||||
@@ -28,7 +28,9 @@ use bevy_xr::session::XrStatus;
|
|||||||
use bevy_xr::session::XrStatusChanged;
|
use bevy_xr::session::XrStatusChanged;
|
||||||
|
|
||||||
use crate::error::OxrError;
|
use crate::error::OxrError;
|
||||||
|
use crate::features::overlay::OxrOverlaySessionEvent;
|
||||||
use crate::graphics::*;
|
use crate::graphics::*;
|
||||||
|
use crate::openxr::exts::OxrEnabledExtensions;
|
||||||
use crate::resources::*;
|
use crate::resources::*;
|
||||||
use crate::session::OxrSession;
|
use crate::session::OxrSession;
|
||||||
use crate::session::OxrSessionCreateNextChain;
|
use crate::session::OxrSessionCreateNextChain;
|
||||||
@@ -97,7 +99,9 @@ impl Plugin for OxrInitPlugin {
|
|||||||
system_id,
|
system_id,
|
||||||
WgpuGraphics(device, queue, adapter_info, adapter, wgpu_instance),
|
WgpuGraphics(device, queue, adapter_info, adapter, wgpu_instance),
|
||||||
session_create_info,
|
session_create_info,
|
||||||
|
enabled_exts,
|
||||||
)) => {
|
)) => {
|
||||||
|
app.insert_resource(enabled_exts);
|
||||||
app.add_plugins((
|
app.add_plugins((
|
||||||
RenderPlugin {
|
RenderPlugin {
|
||||||
render_creation: RenderCreation::manual(
|
render_creation: RenderCreation::manual(
|
||||||
@@ -197,7 +201,15 @@ pub fn update_root_transform(
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl OxrInitPlugin {
|
impl OxrInitPlugin {
|
||||||
fn init_xr(&self) -> Result<(OxrInstance, OxrSystemId, WgpuGraphics, SessionConfigInfo)> {
|
fn init_xr(
|
||||||
|
&self,
|
||||||
|
) -> Result<(
|
||||||
|
OxrInstance,
|
||||||
|
OxrSystemId,
|
||||||
|
WgpuGraphics,
|
||||||
|
SessionConfigInfo,
|
||||||
|
OxrEnabledExtensions,
|
||||||
|
)> {
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
let entry = OxrEntry(openxr::Entry::linked());
|
let entry = OxrEntry(openxr::Entry::linked());
|
||||||
#[cfg(not(windows))]
|
#[cfg(not(windows))]
|
||||||
@@ -236,7 +248,7 @@ impl OxrInitPlugin {
|
|||||||
|
|
||||||
let instance = entry.create_instance(
|
let instance = entry.create_instance(
|
||||||
self.app_info.clone(),
|
self.app_info.clone(),
|
||||||
exts,
|
exts.clone(),
|
||||||
// &["XR_APILAYER_LUNARG_api_dump"],
|
// &["XR_APILAYER_LUNARG_api_dump"],
|
||||||
&[],
|
&[],
|
||||||
backend,
|
backend,
|
||||||
@@ -274,6 +286,7 @@ impl OxrInitPlugin {
|
|||||||
OxrSystemId(system_id),
|
OxrSystemId(system_id),
|
||||||
graphics,
|
graphics,
|
||||||
session_create_info,
|
session_create_info,
|
||||||
|
OxrEnabledExtensions(exts),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -495,6 +508,7 @@ pub fn poll_events(
|
|||||||
mut status: ResMut<XrStatus>,
|
mut status: ResMut<XrStatus>,
|
||||||
mut changed_event: EventWriter<XrStatusChanged>,
|
mut changed_event: EventWriter<XrStatusChanged>,
|
||||||
mut session_status_events: EventWriter<OxrSessionStatusEvent>,
|
mut session_status_events: EventWriter<OxrSessionStatusEvent>,
|
||||||
|
mut overlay_writer: Option<ResMut<Events<OxrOverlaySessionEvent>>>,
|
||||||
) {
|
) {
|
||||||
let _span = info_span!("xr_poll_events");
|
let _span = info_span!("xr_poll_events");
|
||||||
let mut buffer = Default::default();
|
let mut buffer = Default::default();
|
||||||
@@ -534,6 +548,16 @@ pub fn poll_events(
|
|||||||
}
|
}
|
||||||
InstanceLossPending(_) => {}
|
InstanceLossPending(_) => {}
|
||||||
EventsLost(e) => warn!("lost {} XR events", e.lost_event_count()),
|
EventsLost(e) => warn!("lost {} XR events", e.lost_event_count()),
|
||||||
|
MainSessionVisibilityChangedEXTX(d) => {
|
||||||
|
if let Some(writer) = overlay_writer.as_mut() {
|
||||||
|
writer.send(OxrOverlaySessionEvent::MainSessionVisibilityChanged {
|
||||||
|
visible: d.visible(),
|
||||||
|
flags: d.flags(),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
warn!("Overlay Event Recieved without the OverlayPlugin being added!");
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,12 +26,12 @@ pub mod graphics;
|
|||||||
pub mod helper_traits;
|
pub mod helper_traits;
|
||||||
pub mod init;
|
pub mod init;
|
||||||
pub mod layer_builder;
|
pub mod layer_builder;
|
||||||
|
pub mod next_chain;
|
||||||
pub mod reference_space;
|
pub mod reference_space;
|
||||||
pub mod render;
|
pub mod render;
|
||||||
pub mod resources;
|
pub mod resources;
|
||||||
pub mod session;
|
pub mod session;
|
||||||
pub mod types;
|
pub mod types;
|
||||||
pub mod next_chain;
|
|
||||||
|
|
||||||
pub fn add_xr_plugins<G: PluginGroup>(plugins: G) -> PluginGroupBuilder {
|
pub fn add_xr_plugins<G: PluginGroup>(plugins: G) -> PluginGroupBuilder {
|
||||||
plugins
|
plugins
|
||||||
@@ -49,6 +49,7 @@ pub fn add_xr_plugins<G: PluginGroup>(plugins: G) -> PluginGroupBuilder {
|
|||||||
.add(action_set_attaching::OxrActionAttachingPlugin)
|
.add(action_set_attaching::OxrActionAttachingPlugin)
|
||||||
.add(action_binding::OxrActionBindingPlugin)
|
.add(action_binding::OxrActionBindingPlugin)
|
||||||
.add(action_set_syncing::OxrActionSyncingPlugin)
|
.add(action_set_syncing::OxrActionSyncingPlugin)
|
||||||
|
.add(features::overlay::OxrOverlayPlugin)
|
||||||
// .add(XrActionPlugin)
|
// .add(XrActionPlugin)
|
||||||
// we should probably handle the exiting ourselfs so that we can correctly end the
|
// we should probably handle the exiting ourselfs so that we can correctly end the
|
||||||
// session and instance
|
// session and instance
|
||||||
|
|||||||
Reference in New Issue
Block a user