Merge pull request #158 from Schmarni-Dev/is_openxr-xr_flags
Backend Specific RunConditions and Space Flags in xr crate
This commit is contained in:
@@ -14,5 +14,6 @@ bevy = { version = "0.14.0", default-features = false, features = [
|
||||
"bevy_render",
|
||||
"bevy_core_pipeline",
|
||||
"bevy_winit",
|
||||
"bevy_pbr",
|
||||
"x11",
|
||||
] }
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use crate::session::OxrSession;
|
||||
use crate::{openxr_session_running, session::OxrSession};
|
||||
use bevy::prelude::*;
|
||||
use bevy_mod_xr::session::session_running;
|
||||
|
||||
#[derive(SystemSet, Debug, Hash, PartialEq, Eq, Clone, Copy)]
|
||||
pub struct OxrActionSetSyncSet;
|
||||
@@ -10,7 +9,9 @@ impl Plugin for OxrActionSyncingPlugin {
|
||||
app.add_event::<OxrSyncActionSet>();
|
||||
app.add_systems(
|
||||
PreUpdate,
|
||||
sync_sets.in_set(OxrActionSetSyncSet).run_if(session_running), // .in_set(OxrPreUpdateSet::SyncActions),
|
||||
sync_sets
|
||||
.in_set(OxrActionSetSyncSet)
|
||||
.run_if(openxr_session_running),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
use bevy::prelude::*;
|
||||
use bevy_mod_xr::hands::{HandBone, HandBoneRadius};
|
||||
use bevy_mod_xr::hands::{LeftHand, RightHand, XrHandBoneEntities, HAND_JOINT_COUNT};
|
||||
use bevy_mod_xr::session::{XrPreDestroySession, XrSessionCreated, XrTrackingRoot};
|
||||
use bevy_mod_xr::spaces::{XrPrimaryReferenceSpace, XrReferenceSpace, XrVelocity};
|
||||
use bevy_mod_xr::{
|
||||
hands::{HandBone, HandBoneRadius},
|
||||
session::session_running,
|
||||
use bevy_mod_xr::spaces::{
|
||||
XrPrimaryReferenceSpace, XrReferenceSpace, XrSpaceLocationFlags, XrSpaceVelocityFlags,
|
||||
XrVelocity,
|
||||
};
|
||||
use openxr::{SpaceLocationFlags, SpaceVelocityFlags};
|
||||
|
||||
use crate::helper_traits::ToVec3;
|
||||
use crate::openxr_session_running;
|
||||
use crate::resources::OxrFrameState;
|
||||
use crate::resources::Pipelined;
|
||||
use crate::session::OxrSession;
|
||||
@@ -27,7 +28,7 @@ impl Default for HandTrackingPlugin {
|
||||
|
||||
impl Plugin for HandTrackingPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.add_systems(PreUpdate, locate_hands.run_if(session_running));
|
||||
app.add_systems(PreUpdate, locate_hands.run_if(openxr_session_running));
|
||||
if self.default_hands {
|
||||
app.add_systems(XrPreDestroySession, clean_up_default_hands)
|
||||
.add_systems(XrSessionCreated, spawn_default_hands);
|
||||
@@ -49,6 +50,7 @@ pub fn spawn_hand_bones<T: Bundle + Clone>(
|
||||
bone,
|
||||
HandBoneRadius(0.0),
|
||||
OxrSpaceLocationFlags(openxr::SpaceLocationFlags::default()),
|
||||
XrSpaceLocationFlags::default(),
|
||||
))
|
||||
.insert(bundle.clone())
|
||||
.id();
|
||||
@@ -140,7 +142,9 @@ fn locate_hands(
|
||||
&mut Transform,
|
||||
Option<&mut XrVelocity>,
|
||||
&mut OxrSpaceLocationFlags,
|
||||
&mut XrSpaceLocationFlags,
|
||||
Option<&mut OxrSpaceVelocityFlags>,
|
||||
Option<&mut XrSpaceVelocityFlags>,
|
||||
)>,
|
||||
pipelined: Option<Res<Pipelined>>,
|
||||
) {
|
||||
@@ -161,13 +165,21 @@ fn locate_hands(
|
||||
let ref_space = ref_space.map(|v| &v.0).unwrap_or(&default_ref_space.0);
|
||||
let mut clear_flags = || {
|
||||
for e in hand_entities.0.iter() {
|
||||
let Ok((_, _, _, _, mut flags, vel_flags)) = bone_query.get_mut(*e) else {
|
||||
let Ok((_, _, _, _, mut flags, mut xr_flags, vel_flags, xr_vel_flags)) =
|
||||
bone_query.get_mut(*e)
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
flags.0 = SpaceLocationFlags::EMPTY;
|
||||
if let Some(mut flags) = vel_flags {
|
||||
flags.0 = SpaceVelocityFlags::EMPTY;
|
||||
}
|
||||
xr_flags.position_tracked = false;
|
||||
xr_flags.rotation_tracked = false;
|
||||
if let Some(mut flags) = xr_vel_flags {
|
||||
flags.linear_valid = false;
|
||||
flags.angular_valid = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
let (joints, vels) = if wants_velocities {
|
||||
@@ -217,8 +229,16 @@ fn locate_hands(
|
||||
continue;
|
||||
}
|
||||
};
|
||||
for (bone, mut bone_radius, mut transform, velocity, mut location_flags, velocity_flags) in
|
||||
bone_entities
|
||||
for (
|
||||
bone,
|
||||
mut bone_radius,
|
||||
mut transform,
|
||||
velocity,
|
||||
mut location_flags,
|
||||
mut xr_location_flags,
|
||||
velocity_flags,
|
||||
xr_velocity_flags,
|
||||
) in bone_entities
|
||||
{
|
||||
let joint = joints[*bone as usize];
|
||||
if let Some(mut velocity) = velocity {
|
||||
@@ -230,6 +250,10 @@ fn locate_hands(
|
||||
error!("somehow got a hand bone with an XrVelocity component, but without velocity flags");
|
||||
continue;
|
||||
};
|
||||
let Some(mut xr_vel_flags) = xr_velocity_flags else {
|
||||
error!("somehow got a hand bone with an XrVelocity component, but without velocity flags");
|
||||
continue;
|
||||
};
|
||||
let vel = vels[*bone as usize];
|
||||
let flags = OxrSpaceVelocityFlags(vel.velocity_flags);
|
||||
if flags.linear_valid() {
|
||||
@@ -238,6 +262,8 @@ fn locate_hands(
|
||||
if flags.angular_valid() {
|
||||
velocity.angular = vel.angular_velocity.to_vec3();
|
||||
}
|
||||
xr_vel_flags.linear_valid = flags.linear_valid();
|
||||
xr_vel_flags.angular_valid = flags.angular_valid();
|
||||
*vel_flags = flags;
|
||||
}
|
||||
|
||||
@@ -255,6 +281,8 @@ fn locate_hands(
|
||||
transform.rotation.z = joint.pose.orientation.z;
|
||||
transform.rotation.w = joint.pose.orientation.w;
|
||||
}
|
||||
xr_location_flags.position_tracked = flags.pos_valid() && flags.pos_tracked();
|
||||
xr_location_flags.rotation_tracked = flags.rot_valid() && flags.rot_tracked();
|
||||
*location_flags = flags;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
use std::{mem, ptr};
|
||||
|
||||
use bevy::prelude::*;
|
||||
use bevy_mod_xr::session::session_available;
|
||||
use openxr::sys;
|
||||
|
||||
use crate::{
|
||||
next_chain::{OxrNextChainStructBase, OxrNextChainStructProvider},
|
||||
openxr::exts::OxrEnabledExtensions,
|
||||
openxr_session_available,
|
||||
session::{OxrSessionCreateNextChain, OxrSessionCreateNextProvider},
|
||||
};
|
||||
|
||||
@@ -16,7 +16,10 @@ 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.run_if(session_available));
|
||||
app.add_systems(
|
||||
First,
|
||||
add_overlay_info_to_chain.run_if(openxr_session_available),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::sync::Arc;
|
||||
|
||||
use bevy::ecs::system::RunSystemOnce;
|
||||
use bevy::prelude::*;
|
||||
use bevy::render::extract_resource::ExtractResource;
|
||||
use bevy::render::extract_resource::ExtractResourcePlugin;
|
||||
use bevy::render::renderer::RenderAdapter;
|
||||
use bevy::render::renderer::RenderAdapterInfo;
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
// use actions::XrActionPlugin;
|
||||
use bevy::{
|
||||
app::{PluginGroup, PluginGroupBuilder},
|
||||
prelude::Res,
|
||||
render::RenderPlugin,
|
||||
utils::default,
|
||||
window::{PresentMode, Window, WindowPlugin},
|
||||
};
|
||||
use bevy_mod_xr::camera::XrCameraPlugin;
|
||||
use bevy_mod_xr::session::XrSessionPlugin;
|
||||
use bevy_mod_xr::{camera::XrCameraPlugin, session::XrState};
|
||||
use init::OxrInitPlugin;
|
||||
use render::OxrRenderPlugin;
|
||||
use resources::OxrInstance;
|
||||
use session::OxrSession;
|
||||
|
||||
use self::{
|
||||
features::{handtracking::HandTrackingPlugin, passthrough::OxrPassthroughPlugin},
|
||||
@@ -33,6 +36,23 @@ pub mod session;
|
||||
pub mod spaces;
|
||||
pub mod types;
|
||||
|
||||
/// A [`Condition`](bevy::ecs::schedule::Condition) system that says if the OpenXR session is available.
|
||||
pub fn openxr_session_available(
|
||||
status: Option<Res<XrState>>,
|
||||
instance: Option<Res<OxrInstance>>,
|
||||
) -> bool {
|
||||
status.is_some_and(|s| *s != XrState::Unavailable) && instance.is_some()
|
||||
}
|
||||
|
||||
/// A [`Condition`](bevy::ecs::schedule::Condition) system that says if the OpenXR is running.
|
||||
/// use this when working with OpenXR specific things
|
||||
pub fn openxr_session_running(
|
||||
status: Option<Res<XrState>>,
|
||||
session: Option<Res<OxrSession>>,
|
||||
) -> bool {
|
||||
matches!(status.as_deref(), Some(XrState::Running)) & session.is_some()
|
||||
}
|
||||
|
||||
pub fn add_xr_plugins<G: PluginGroup>(plugins: G) -> PluginGroupBuilder {
|
||||
plugins
|
||||
.build()
|
||||
|
||||
@@ -7,7 +7,7 @@ use bevy_mod_xr::{
|
||||
spaces::{XrPrimaryReferenceSpace, XrReferenceSpace},
|
||||
};
|
||||
|
||||
use crate::{init::create_xr_session, session::OxrSession};
|
||||
use crate::session::OxrSession;
|
||||
|
||||
pub struct OxrReferenceSpacePlugin {
|
||||
pub default_primary_ref_space: openxr::ReferenceSpaceType,
|
||||
|
||||
@@ -2,8 +2,11 @@ use std::{mem::MaybeUninit, ptr, sync::Mutex};
|
||||
|
||||
use bevy::{prelude::*, utils::hashbrown::HashSet};
|
||||
use bevy_mod_xr::{
|
||||
session::{session_available, session_running, XrFirst, XrHandleEvents},
|
||||
spaces::{XrDestroySpace, XrPrimaryReferenceSpace, XrReferenceSpace, XrSpace, XrVelocity},
|
||||
session::{XrFirst, XrHandleEvents},
|
||||
spaces::{
|
||||
XrDestroySpace, XrPrimaryReferenceSpace, XrReferenceSpace, XrSpace, XrSpaceLocationFlags,
|
||||
XrSpaceVelocityFlags, XrVelocity,
|
||||
},
|
||||
types::XrPose,
|
||||
};
|
||||
use openxr::{
|
||||
@@ -13,6 +16,7 @@ use openxr::{
|
||||
|
||||
use crate::{
|
||||
helper_traits::{ToPosef, ToQuat, ToVec3},
|
||||
openxr_session_available, openxr_session_running,
|
||||
resources::{OxrFrameState, OxrInstance, Pipelined},
|
||||
session::OxrSession,
|
||||
};
|
||||
@@ -24,7 +28,10 @@ pub struct OxrSpaceSyncSet;
|
||||
pub struct OxrSpacePatchingPlugin;
|
||||
impl Plugin for OxrSpacePatchingPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.add_systems(Startup, patch_destroy_space.run_if(session_available));
|
||||
app.add_systems(
|
||||
Startup,
|
||||
patch_destroy_space.run_if(openxr_session_available),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,13 +43,13 @@ impl Plugin for OxrSpatialPlugin {
|
||||
XrFirst,
|
||||
destroy_space_event
|
||||
.before(XrHandleEvents::Poll)
|
||||
.run_if(session_available),
|
||||
.run_if(openxr_session_available),
|
||||
)
|
||||
.add_systems(
|
||||
PreUpdate,
|
||||
update_space_transforms
|
||||
.in_set(OxrSpaceSyncSet)
|
||||
.run_if(session_running),
|
||||
.run_if(openxr_session_running),
|
||||
)
|
||||
.observe(add_location_flags)
|
||||
.observe(add_velocity_flags);
|
||||
@@ -151,7 +158,9 @@ fn update_space_transforms(
|
||||
Option<&mut XrVelocity>,
|
||||
Option<&XrReferenceSpace>,
|
||||
&mut OxrSpaceLocationFlags,
|
||||
&mut XrSpaceLocationFlags,
|
||||
Option<&mut OxrSpaceVelocityFlags>,
|
||||
Option<&mut XrSpaceVelocityFlags>,
|
||||
)>,
|
||||
) {
|
||||
for (
|
||||
@@ -159,8 +168,10 @@ fn update_space_transforms(
|
||||
space,
|
||||
velocity,
|
||||
ref_space,
|
||||
mut space_location_flags,
|
||||
space_velocity_flags,
|
||||
mut oxr_space_location_flags,
|
||||
mut xr_space_location_flags,
|
||||
oxr_space_velocity_flags,
|
||||
xr_space_velocity_flags,
|
||||
) in &mut query
|
||||
{
|
||||
let ref_space = ref_space.unwrap_or(&default_ref_space);
|
||||
@@ -182,11 +193,17 @@ fn update_space_transforms(
|
||||
if flags.linear_valid() {
|
||||
velocity.linear = space_velocity.linear_velocity.to_vec3();
|
||||
}
|
||||
let Some(mut vel_flags) = space_velocity_flags else {
|
||||
let Some(mut vel_flags) = oxr_space_velocity_flags else {
|
||||
error!("XrVelocity without OxrSpaceVelocityFlags");
|
||||
return;
|
||||
};
|
||||
let Some(mut xr_vel_flags) = xr_space_velocity_flags else {
|
||||
error!("XrVelocity without XrSpaceVelocityFlags");
|
||||
return;
|
||||
};
|
||||
*vel_flags = flags;
|
||||
xr_vel_flags.linear_valid = vel_flags.linear_valid();
|
||||
xr_vel_flags.angular_valid = vel_flags.angular_valid();
|
||||
Ok(location)
|
||||
}
|
||||
Err(err) => Err(err),
|
||||
@@ -202,7 +219,9 @@ fn update_space_transforms(
|
||||
if flags.rot_valid() {
|
||||
transform.rotation = space_location.pose.orientation.to_quat();
|
||||
}
|
||||
*space_location_flags = flags;
|
||||
*oxr_space_location_flags = flags;
|
||||
xr_space_location_flags.position_tracked = flags.pos_valid() && flags.pos_tracked();
|
||||
xr_space_location_flags.rotation_tracked = flags.rot_valid() && flags.rot_tracked();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -266,6 +266,7 @@ pub fn status_changed_to(
|
||||
}
|
||||
|
||||
/// A [`Condition`](bevy::ecs::schedule::Condition) system that says if the XR session is available. Returns true as long as [`XrState`] exists and isn't [`Unavailable`](XrStatus::Unavailable).
|
||||
/// When using backend specific resources use the backend specific condition
|
||||
pub fn session_available(status: Option<Res<XrState>>) -> bool {
|
||||
status.is_some_and(|s| *s != XrState::Unavailable)
|
||||
}
|
||||
@@ -282,7 +283,8 @@ pub fn session_ready_or_running(status: Option<Res<XrState>>) -> bool {
|
||||
matches!(status.as_deref(), Some(XrState::Ready | XrState::Running))
|
||||
}
|
||||
|
||||
/// A [`Condition`](bevy::ecs::schedule::Condition) system that says if the XR session is running
|
||||
/// A [`Condition`](bevy::ecs::schedule::Condition) system that says if the XR session is running.
|
||||
/// When using backend specific resources use the backend specific condition
|
||||
pub fn session_running(status: Option<Res<XrState>>) -> bool {
|
||||
matches!(status.as_deref(), Some(XrState::Running))
|
||||
}
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
use bevy::{
|
||||
ecs::component::StorageType,
|
||||
prelude::*,
|
||||
render::{extract_component::ExtractComponent, extract_resource::ExtractResource},
|
||||
};
|
||||
|
||||
/// Any Spaces will be invalid after the owning session exits
|
||||
#[repr(transparent)]
|
||||
#[derive(Clone, Copy, Hash, PartialEq, Eq, Reflect, Debug, Component, ExtractComponent)]
|
||||
#[derive(Clone, Copy, Hash, PartialEq, Eq, Reflect, Debug, ExtractComponent)]
|
||||
pub struct XrSpace(u64);
|
||||
|
||||
#[derive(Clone, Copy, Reflect, Debug, Component, ExtractComponent, Default)]
|
||||
#[derive(Clone, Copy, Reflect, Debug, ExtractComponent, Default)]
|
||||
pub struct XrVelocity {
|
||||
/// Velocity of a space relative to it's reference space
|
||||
pub linear: Vec3,
|
||||
@@ -42,6 +43,22 @@ pub struct XrReferenceSpace(pub XrSpace);
|
||||
)]
|
||||
pub struct XrPrimaryReferenceSpace(pub XrReferenceSpace);
|
||||
|
||||
#[derive(
|
||||
Clone, Copy, Hash, PartialEq, Eq, Reflect, Debug, Component, ExtractComponent, Default,
|
||||
)]
|
||||
pub struct XrSpaceLocationFlags {
|
||||
pub position_tracked: bool,
|
||||
pub rotation_tracked: bool,
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Clone, Copy, Hash, PartialEq, Eq, Reflect, Debug, Component, ExtractComponent, Default,
|
||||
)]
|
||||
pub struct XrSpaceVelocityFlags {
|
||||
pub linear_valid: bool,
|
||||
pub angular_valid: bool,
|
||||
}
|
||||
|
||||
impl XrSpace {
|
||||
/// # Safety
|
||||
/// only call with known valid handles
|
||||
@@ -52,3 +69,28 @@ impl XrSpace {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Component for XrSpace {
|
||||
const STORAGE_TYPE: StorageType = StorageType::Table;
|
||||
|
||||
fn register_component_hooks(hooks: &mut bevy::ecs::component::ComponentHooks) {
|
||||
hooks.on_add(|mut world, entity, _| {
|
||||
world
|
||||
.commands()
|
||||
.entity(entity)
|
||||
.insert(XrSpaceLocationFlags::default());
|
||||
});
|
||||
}
|
||||
}
|
||||
impl Component for XrVelocity {
|
||||
const STORAGE_TYPE: StorageType = StorageType::Table;
|
||||
|
||||
fn register_component_hooks(hooks: &mut bevy::ecs::component::ComponentHooks) {
|
||||
hooks.on_add(|mut world, entity, _| {
|
||||
world
|
||||
.commands()
|
||||
.entity(entity)
|
||||
.insert(XrSpaceVelocityFlags::default());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user