Fallback to flat when no oxr runtime is found (#51)
* basics done? now to the fun part: changing the ENTIRE lib to work with xr and non xr * updated stuff and renamed file * actually add the renamed file into git lol :3 * made lib fallback to flat when no runtime is found but can't compile with default settings under those circumstances
This commit is contained in:
@@ -18,6 +18,7 @@ members = ["examples/android", "examples/demo"]
|
|||||||
anyhow = "1.0.75"
|
anyhow = "1.0.75"
|
||||||
ash = "0.37.3"
|
ash = "0.37.3"
|
||||||
bevy = "0.12"
|
bevy = "0.12"
|
||||||
|
futures-lite = "2.1.0"
|
||||||
mint = "0.5.9"
|
mint = "0.5.9"
|
||||||
wgpu = "0.17.1"
|
wgpu = "0.17.1"
|
||||||
wgpu-core = { version = "0.17.1", features = ["vulkan"] }
|
wgpu-core = { version = "0.17.1", features = ["vulkan"] }
|
||||||
|
|||||||
@@ -17,4 +17,5 @@ color-eyre = "0.6.2"
|
|||||||
|
|
||||||
[target.'cfg(not(target_os="android"))'.dependencies.bevy_oxr]
|
[target.'cfg(not(target_os="android"))'.dependencies.bevy_oxr]
|
||||||
path = "../../"
|
path = "../../"
|
||||||
|
# May need to be more specific. needs to be false at least on linux without an active runtime to run in flat
|
||||||
default-features = true
|
default-features = true
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "demo"
|
|
||||||
version = "0.1.0"
|
|
||||||
edition = "2021"
|
|
||||||
|
|
||||||
|
|
||||||
[lib]
|
|
||||||
crate-type = ["cdylib", "lib"]
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
bevy = { git = "https://github.com/bevyengine/bevy.git" }
|
|
||||||
# bevy = "0.11.3"
|
|
||||||
# default-features is false because it for some reason complains when trying to statically link openxr
|
|
||||||
bevy_oxr = { path = "../../" }
|
|
||||||
# bevy_openxr = { git = "https://github.com/Schmarni-Dev/bevy_openxr", default-features = false, branch = "demo"}
|
|
||||||
bevy_rapier3d = { git = "https://github.com/devil-ira/bevy_rapier", version = "0.22.0", branch = "bevy-0.12" }
|
|
||||||
# bevy_rapier3d = { git = "https://github.com/Schmarni-Dev/bevy_rapier" }
|
|
||||||
color-eyre = "0.6.2"
|
|
||||||
|
|
||||||
[profile.release]
|
|
||||||
lto = "fat"
|
|
||||||
codegen-units = 1
|
|
||||||
panic = "abort"
|
|
||||||
@@ -3,6 +3,7 @@ use std::{f32::consts::PI, ops::Mul, time::Duration};
|
|||||||
use bevy::{
|
use bevy::{
|
||||||
diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin},
|
diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin},
|
||||||
ecs::schedule::ScheduleLabel,
|
ecs::schedule::ScheduleLabel,
|
||||||
|
input::{keyboard::KeyCode, Input},
|
||||||
log::info,
|
log::info,
|
||||||
prelude::{
|
prelude::{
|
||||||
bevy_main, default, shape, App, Assets, Color, Commands, Component, Entity, Event,
|
bevy_main, default, shape, App, Assets, Color, Commands, Component, Entity, Event,
|
||||||
@@ -16,10 +17,12 @@ use bevy::{
|
|||||||
};
|
};
|
||||||
use bevy_oxr::{
|
use bevy_oxr::{
|
||||||
input::XrInput,
|
input::XrInput,
|
||||||
|
xr_init::{XrEnableRequest, XrEnableStatus, xr_only},
|
||||||
resources::{XrFrameState, XrInstance, XrSession},
|
resources::{XrFrameState, XrInstance, XrSession},
|
||||||
xr_input::{
|
xr_input::{
|
||||||
|
actions::XrActionSets,
|
||||||
debug_gizmos::OpenXrDebugRenderer,
|
debug_gizmos::OpenXrDebugRenderer,
|
||||||
hands::common::{ HandInputDebugRenderer, HandResource, HandsResource, OpenXrHandInput},
|
hands::common::{HandInputDebugRenderer, HandResource, HandsResource, OpenXrHandInput},
|
||||||
hands::HandBone,
|
hands::HandBone,
|
||||||
interactions::{
|
interactions::{
|
||||||
draw_interaction_gizmos, draw_socket_gizmos, interactions, socket_interactions,
|
draw_interaction_gizmos, draw_socket_gizmos, interactions, socket_interactions,
|
||||||
@@ -29,11 +32,25 @@ use bevy_oxr::{
|
|||||||
oculus_touch::OculusController,
|
oculus_touch::OculusController,
|
||||||
prototype_locomotion::{proto_locomotion, PrototypeLocomotionConfig},
|
prototype_locomotion::{proto_locomotion, PrototypeLocomotionConfig},
|
||||||
trackers::{OpenXRController, OpenXRLeftController, OpenXRRightController, OpenXRTracker},
|
trackers::{OpenXRController, OpenXRLeftController, OpenXRRightController, OpenXRTracker},
|
||||||
Hand, actions::XrActionSets,
|
Hand,
|
||||||
},
|
},
|
||||||
DefaultXrPlugins,
|
DefaultXrPlugins,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
fn input_stuff(
|
||||||
|
keys: Res<Input<KeyCode>>,
|
||||||
|
status: Res<XrEnableStatus>,
|
||||||
|
mut request: EventWriter<XrEnableRequest>,
|
||||||
|
) {
|
||||||
|
if keys.just_pressed(KeyCode::Space) {
|
||||||
|
match status.into_inner() {
|
||||||
|
XrEnableStatus::Enabled => request.send(XrEnableRequest::TryDisable),
|
||||||
|
XrEnableStatus::Disabled => request.send(XrEnableRequest::TryEnable),
|
||||||
|
XrEnableStatus::Waiting => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mod setup;
|
mod setup;
|
||||||
use crate::setup::setup_scene;
|
use crate::setup::setup_scene;
|
||||||
use bevy_rapier3d::prelude::*;
|
use bevy_rapier3d::prelude::*;
|
||||||
@@ -45,7 +62,7 @@ pub fn main() {
|
|||||||
info!("Running bevy_openxr demo");
|
info!("Running bevy_openxr demo");
|
||||||
let mut app = App::new();
|
let mut app = App::new();
|
||||||
|
|
||||||
app
|
app.add_systems(Update, input_stuff)
|
||||||
//lets get the usual diagnostic stuff added
|
//lets get the usual diagnostic stuff added
|
||||||
.add_plugins(LogDiagnosticsPlugin::default())
|
.add_plugins(LogDiagnosticsPlugin::default())
|
||||||
.add_plugins(FrameTimeDiagnosticsPlugin)
|
.add_plugins(FrameTimeDiagnosticsPlugin)
|
||||||
@@ -60,11 +77,11 @@ pub fn main() {
|
|||||||
.add_systems(Startup, setup_scene)
|
.add_systems(Startup, setup_scene)
|
||||||
.add_systems(Startup, spawn_controllers_example) //you need to spawn controllers or it crashes TODO:: Fix this
|
.add_systems(Startup, spawn_controllers_example) //you need to spawn controllers or it crashes TODO:: Fix this
|
||||||
//add locomotion
|
//add locomotion
|
||||||
.add_systems(Update, proto_locomotion)
|
.add_systems(Update, proto_locomotion.run_if(xr_only()))
|
||||||
.insert_resource(PrototypeLocomotionConfig::default())
|
.insert_resource(PrototypeLocomotionConfig::default())
|
||||||
//lets add the interaction systems
|
//lets add the interaction systems
|
||||||
.add_event::<InteractionEvent>()
|
.add_event::<InteractionEvent>()
|
||||||
.add_systems(Update, prototype_interaction_input)
|
.add_systems(Update, prototype_interaction_input.run_if(xr_only()))
|
||||||
.add_systems(Update, interactions.before(update_interactable_states))
|
.add_systems(Update, interactions.before(update_interactable_states))
|
||||||
.add_systems(Update, update_interactable_states)
|
.add_systems(Update, update_interactable_states)
|
||||||
.add_systems(
|
.add_systems(
|
||||||
@@ -76,7 +93,7 @@ pub fn main() {
|
|||||||
//draw the interaction gizmos
|
//draw the interaction gizmos
|
||||||
.add_systems(
|
.add_systems(
|
||||||
Update,
|
Update,
|
||||||
draw_interaction_gizmos.after(update_interactable_states),
|
draw_interaction_gizmos.run_if(xr_only()).after(update_interactable_states),
|
||||||
)
|
)
|
||||||
.add_systems(Update, draw_socket_gizmos.after(update_interactable_states))
|
.add_systems(Update, draw_socket_gizmos.after(update_interactable_states))
|
||||||
//add our cube spawning system
|
//add our cube spawning system
|
||||||
@@ -85,7 +102,7 @@ pub fn main() {
|
|||||||
0.25,
|
0.25,
|
||||||
bevy::time::TimerMode::Once,
|
bevy::time::TimerMode::Once,
|
||||||
)))
|
)))
|
||||||
.add_systems(Update, request_cube_spawn)
|
.add_systems(Update, request_cube_spawn.run_if(xr_only()))
|
||||||
.add_systems(Update, cube_spawner.after(request_cube_spawn))
|
.add_systems(Update, cube_spawner.after(request_cube_spawn))
|
||||||
//test capsule
|
//test capsule
|
||||||
.add_systems(Startup, spawn_capsule)
|
.add_systems(Startup, spawn_capsule)
|
||||||
|
|||||||
@@ -1,609 +0,0 @@
|
|||||||
use bevy::{
|
|
||||||
diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin},
|
|
||||||
log::info,
|
|
||||||
prelude::{
|
|
||||||
*,
|
|
||||||
bevy_main, default, shape, App, Assets, Color, Commands, Component, Event, EventReader,
|
|
||||||
EventWriter, GlobalTransform, IntoSystemConfigs, IntoSystemSetConfigs, Mesh, PbrBundle,
|
|
||||||
PostUpdate, Query, Res, ResMut, Resource, SpatialBundle, StandardMaterial, Startup,
|
|
||||||
Transform, Update, With, Without,
|
|
||||||
},
|
|
||||||
time::{Time, Timer},
|
|
||||||
transform::TransformSystem,
|
|
||||||
};
|
|
||||||
use bevy_openxr::{
|
|
||||||
input::XrInput,
|
|
||||||
resources::{XrFrameState, XrInstance, XrSession},
|
|
||||||
xr_input::{
|
|
||||||
debug_gizmos::OpenXrDebugRenderer,
|
|
||||||
hand::{HandBone, HandInputDebugRenderer, HandResource, HandsResource, OpenXrHandInput},
|
|
||||||
interactions::{
|
|
||||||
draw_interaction_gizmos, draw_socket_gizmos, interactions, socket_interactions,
|
|
||||||
update_interactable_states, InteractionEvent, Touched, XRDirectInteractor,
|
|
||||||
XRInteractable, XRInteractableState, XRInteractorState, XRSelection,
|
|
||||||
},
|
|
||||||
oculus_touch::OculusController,
|
|
||||||
prototype_locomotion::{proto_locomotion, PrototypeLocomotionConfig},
|
|
||||||
trackers::{OpenXRController, OpenXRLeftController, OpenXRRightController, OpenXRTracker},
|
|
||||||
Hand,
|
|
||||||
},
|
|
||||||
DefaultXrPlugins,
|
|
||||||
};
|
|
||||||
|
|
||||||
mod setup;
|
|
||||||
use crate::setup::setup_scene;
|
|
||||||
use bevy_rapier3d::prelude::*;
|
|
||||||
|
|
||||||
#[bevy_main]
|
|
||||||
pub fn main() {
|
|
||||||
color_eyre::install().unwrap();
|
|
||||||
|
|
||||||
info!("Running bevy_openxr demo");
|
|
||||||
let mut app = App::new();
|
|
||||||
|
|
||||||
app
|
|
||||||
//lets get the usual diagnostic stuff added
|
|
||||||
.add_plugins(LogDiagnosticsPlugin::default())
|
|
||||||
.add_plugins(FrameTimeDiagnosticsPlugin)
|
|
||||||
//lets get the xr defaults added
|
|
||||||
.add_plugins(DefaultXrPlugins)
|
|
||||||
//lets add the debug renderer for the controllers
|
|
||||||
.add_plugins(OpenXrDebugRenderer)
|
|
||||||
//rapier goes here
|
|
||||||
.add_plugins(RapierPhysicsPlugin::<NoUserData>::default().with_default_system_setup(false))
|
|
||||||
.add_plugins(RapierDebugRenderPlugin::default())
|
|
||||||
//lets setup the starting scene
|
|
||||||
.add_systems(Startup, setup_scene)
|
|
||||||
.add_systems(Startup, spawn_controllers_example) //you need to spawn controllers or it crashes TODO:: Fix this
|
|
||||||
//add locomotion
|
|
||||||
.add_systems(Update, proto_locomotion)
|
|
||||||
.insert_resource(PrototypeLocomotionConfig::default())
|
|
||||||
//lets add the interaction systems
|
|
||||||
.add_event::<InteractionEvent>()
|
|
||||||
.add_systems(Update, prototype_interaction_input)
|
|
||||||
.add_systems(Update, interactions.before(update_interactable_states))
|
|
||||||
.add_systems(Update, update_interactable_states)
|
|
||||||
.add_systems(
|
|
||||||
Update,
|
|
||||||
socket_interactions.before(update_interactable_states),
|
|
||||||
)
|
|
||||||
//add the grabbable system
|
|
||||||
.add_systems(Update, update_grabbables.after(update_interactable_states))
|
|
||||||
//draw the interaction gizmos
|
|
||||||
.add_systems(
|
|
||||||
Update,
|
|
||||||
draw_interaction_gizmos.after(update_interactable_states),
|
|
||||||
)
|
|
||||||
.add_systems(Update, draw_socket_gizmos.after(update_interactable_states))
|
|
||||||
//add our cube spawning system
|
|
||||||
.add_event::<SpawnCubeRequest>()
|
|
||||||
.insert_resource(SpawnCubeTimer(Timer::from_seconds(
|
|
||||||
0.25,
|
|
||||||
bevy::time::TimerMode::Once,
|
|
||||||
)))
|
|
||||||
.add_systems(Update, request_cube_spawn)
|
|
||||||
.add_systems(Update, cube_spawner.after(request_cube_spawn))
|
|
||||||
//test capsule
|
|
||||||
.add_systems(Startup, spawn_capsule)
|
|
||||||
//physics hands
|
|
||||||
.add_plugins(OpenXrHandInput)
|
|
||||||
.add_plugins(HandInputDebugRenderer)
|
|
||||||
.add_systems(Startup, spawn_physics_hands)
|
|
||||||
.add_systems(Update, update_physics_hands);
|
|
||||||
|
|
||||||
//configure rapier sets
|
|
||||||
app.configure_sets(
|
|
||||||
PostUpdate,
|
|
||||||
(
|
|
||||||
PhysicsSet::SyncBackend,
|
|
||||||
PhysicsSet::StepSimulation,
|
|
||||||
PhysicsSet::Writeback,
|
|
||||||
)
|
|
||||||
.chain()
|
|
||||||
.before(TransformSystem::TransformPropagate),
|
|
||||||
);
|
|
||||||
//add rapier systems
|
|
||||||
app.add_systems(
|
|
||||||
PostUpdate,
|
|
||||||
(
|
|
||||||
RapierPhysicsPlugin::<NoUserData>::get_systems(PhysicsSet::SyncBackend)
|
|
||||||
.in_set(PhysicsSet::SyncBackend),
|
|
||||||
(
|
|
||||||
RapierPhysicsPlugin::<NoUserData>::get_systems(PhysicsSet::StepSimulation),
|
|
||||||
// despawn_one_box,
|
|
||||||
)
|
|
||||||
.in_set(PhysicsSet::StepSimulation),
|
|
||||||
RapierPhysicsPlugin::<NoUserData>::get_systems(PhysicsSet::Writeback)
|
|
||||||
.in_set(PhysicsSet::Writeback),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
app.run();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn spawn_controllers_example(mut commands: Commands) {
|
|
||||||
//left hand
|
|
||||||
commands.spawn((
|
|
||||||
OpenXRLeftController,
|
|
||||||
OpenXRController,
|
|
||||||
OpenXRTracker,
|
|
||||||
SpatialBundle::default(),
|
|
||||||
XRDirectInteractor,
|
|
||||||
XRInteractorState::default(),
|
|
||||||
XRSelection::default(),
|
|
||||||
));
|
|
||||||
//right hand
|
|
||||||
commands.spawn((
|
|
||||||
OpenXRRightController,
|
|
||||||
OpenXRController,
|
|
||||||
OpenXRTracker,
|
|
||||||
SpatialBundle::default(),
|
|
||||||
XRDirectInteractor,
|
|
||||||
XRInteractorState::default(),
|
|
||||||
XRSelection::default(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn spawn_capsule(
|
|
||||||
mut commands: Commands,
|
|
||||||
mut meshes: ResMut<Assets<Mesh>>,
|
|
||||||
mut materials: ResMut<Assets<StandardMaterial>>,
|
|
||||||
) {
|
|
||||||
commands.spawn((
|
|
||||||
PbrBundle {
|
|
||||||
mesh: meshes.add(Mesh::from(shape::Capsule {
|
|
||||||
radius: 0.033,
|
|
||||||
depth: 0.115,
|
|
||||||
..default()
|
|
||||||
})),
|
|
||||||
material: materials.add(Color::rgb(0.8, 0.7, 0.6).into()),
|
|
||||||
transform: Transform::from_xyz(0.0, 2.0, 0.0),
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
// Collider::capsule_y(0.0575, 0.034),
|
|
||||||
Collider::capsule(
|
|
||||||
Vec3 {
|
|
||||||
x: 0.0,
|
|
||||||
y: -0.0575,
|
|
||||||
z: 0.0,
|
|
||||||
},
|
|
||||||
Vec3 {
|
|
||||||
x: 0.0,
|
|
||||||
y: 0.0575,
|
|
||||||
z: 0.0,
|
|
||||||
},
|
|
||||||
0.034,
|
|
||||||
),
|
|
||||||
RigidBody::Dynamic,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Component, PartialEq, Debug, Clone, Copy)]
|
|
||||||
pub enum PhysicsHandBone {
|
|
||||||
Palm,
|
|
||||||
Wrist,
|
|
||||||
ThumbMetacarpal,
|
|
||||||
ThumbProximal,
|
|
||||||
ThumbDistal,
|
|
||||||
ThumbTip,
|
|
||||||
IndexMetacarpal,
|
|
||||||
IndexProximal,
|
|
||||||
IndexIntermediate,
|
|
||||||
IndexDistal,
|
|
||||||
IndexTip,
|
|
||||||
MiddleMetacarpal,
|
|
||||||
MiddleProximal,
|
|
||||||
MiddleIntermediate,
|
|
||||||
MiddleDistal,
|
|
||||||
MiddleTip,
|
|
||||||
RingMetacarpal,
|
|
||||||
RingProximal,
|
|
||||||
RingIntermediate,
|
|
||||||
RingDistal,
|
|
||||||
RingTip,
|
|
||||||
LittleMetacarpal,
|
|
||||||
LittleProximal,
|
|
||||||
LittleIntermediate,
|
|
||||||
LittleDistal,
|
|
||||||
LittleTip,
|
|
||||||
}
|
|
||||||
#[derive(Component, PartialEq)]
|
|
||||||
pub enum BoneInitState {
|
|
||||||
True,
|
|
||||||
False,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn spawn_physics_hands(mut commands: Commands) {
|
|
||||||
//here we go
|
|
||||||
let hands = [Hand::Left, Hand::Right];
|
|
||||||
let bones = [
|
|
||||||
PhysicsHandBone::Palm,
|
|
||||||
PhysicsHandBone::Wrist,
|
|
||||||
PhysicsHandBone::ThumbMetacarpal,
|
|
||||||
PhysicsHandBone::ThumbProximal,
|
|
||||||
PhysicsHandBone::ThumbDistal,
|
|
||||||
PhysicsHandBone::ThumbTip,
|
|
||||||
PhysicsHandBone::IndexMetacarpal,
|
|
||||||
PhysicsHandBone::IndexProximal,
|
|
||||||
PhysicsHandBone::IndexIntermediate,
|
|
||||||
PhysicsHandBone::IndexDistal,
|
|
||||||
PhysicsHandBone::IndexTip,
|
|
||||||
PhysicsHandBone::MiddleMetacarpal,
|
|
||||||
PhysicsHandBone::MiddleProximal,
|
|
||||||
PhysicsHandBone::MiddleIntermediate,
|
|
||||||
PhysicsHandBone::MiddleDistal,
|
|
||||||
PhysicsHandBone::MiddleTip,
|
|
||||||
PhysicsHandBone::RingMetacarpal,
|
|
||||||
PhysicsHandBone::RingProximal,
|
|
||||||
PhysicsHandBone::RingIntermediate,
|
|
||||||
PhysicsHandBone::RingDistal,
|
|
||||||
PhysicsHandBone::RingTip,
|
|
||||||
PhysicsHandBone::LittleMetacarpal,
|
|
||||||
PhysicsHandBone::LittleProximal,
|
|
||||||
PhysicsHandBone::LittleIntermediate,
|
|
||||||
PhysicsHandBone::LittleDistal,
|
|
||||||
PhysicsHandBone::LittleTip,
|
|
||||||
];
|
|
||||||
//lets just do the Right ThumbMetacarpal for now
|
|
||||||
//i dont understand the groups yet
|
|
||||||
let self_group = Group::GROUP_1;
|
|
||||||
let interaction_group = Group::ALL;
|
|
||||||
let radius = 0.010;
|
|
||||||
|
|
||||||
for hand in hands.iter() {
|
|
||||||
for bone in bones.iter() {
|
|
||||||
//spawn the thing
|
|
||||||
commands.spawn((
|
|
||||||
SpatialBundle::default(),
|
|
||||||
Collider::capsule(
|
|
||||||
Vec3 {
|
|
||||||
x: 0.0,
|
|
||||||
y: -0.0575,
|
|
||||||
z: 0.0,
|
|
||||||
},
|
|
||||||
Vec3 {
|
|
||||||
x: 0.0,
|
|
||||||
y: 0.0575,
|
|
||||||
z: 0.0,
|
|
||||||
},
|
|
||||||
radius,
|
|
||||||
),
|
|
||||||
RigidBody::KinematicPositionBased,
|
|
||||||
// CollisionGroups::new(self_group, interaction_group),
|
|
||||||
// SolverGroups::new(self_group, interaction_group),
|
|
||||||
bone.clone(),
|
|
||||||
BoneInitState::False,
|
|
||||||
hand.clone(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update_physics_hands(
|
|
||||||
hands_res: Option<Res<HandsResource>>,
|
|
||||||
mut bone_query: Query<(
|
|
||||||
&mut Transform,
|
|
||||||
&mut Collider,
|
|
||||||
&PhysicsHandBone,
|
|
||||||
&mut BoneInitState,
|
|
||||||
&Hand,
|
|
||||||
)>,
|
|
||||||
hand_query: Query<(&Transform, &HandBone, &Hand, Without<PhysicsHandBone>)>,
|
|
||||||
) {
|
|
||||||
//sanity check do we even have hands?
|
|
||||||
match hands_res {
|
|
||||||
Some(res) => {
|
|
||||||
//config stuff
|
|
||||||
let radius = 0.010;
|
|
||||||
for mut bone in bone_query.iter_mut() {
|
|
||||||
let hand_res = match bone.4 {
|
|
||||||
Hand::Left => res.left,
|
|
||||||
Hand::Right => res.right,
|
|
||||||
};
|
|
||||||
|
|
||||||
//lets just do the Right ThumbMetacarpal for now
|
|
||||||
let result = get_start_and_end_entities(hand_res, bone.2);
|
|
||||||
if let Some((start_entity, end_entity)) = result {
|
|
||||||
//now we need their transforms
|
|
||||||
let start_components = hand_query.get(start_entity);
|
|
||||||
let end_components = hand_query.get(end_entity);
|
|
||||||
let direction = end_components.unwrap().0.translation
|
|
||||||
- start_components.unwrap().0.translation;
|
|
||||||
if direction.length() < 0.001 {
|
|
||||||
//i hate this but we need to skip init if the length is zero
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
match *bone.3 {
|
|
||||||
BoneInitState::True => {
|
|
||||||
//if we are init then we just move em?
|
|
||||||
*bone.0 = start_components
|
|
||||||
.unwrap()
|
|
||||||
.0
|
|
||||||
.clone()
|
|
||||||
.looking_at(end_components.unwrap().0.translation, Vec3::Y);
|
|
||||||
}
|
|
||||||
BoneInitState::False => {
|
|
||||||
//build a new collider?
|
|
||||||
*bone.1 = Collider::capsule(
|
|
||||||
Vec3::splat(0.0),
|
|
||||||
Vec3 {
|
|
||||||
x: 0.0,
|
|
||||||
y: 0.0,
|
|
||||||
z: -direction.length(),
|
|
||||||
},
|
|
||||||
radius,
|
|
||||||
);
|
|
||||||
*bone.3 = BoneInitState::True;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => info!("hand states resource not initialized yet"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_start_and_end_entities(
|
|
||||||
hand_res: HandResource,
|
|
||||||
bone: &PhysicsHandBone,
|
|
||||||
) -> Option<(Entity, Entity)> {
|
|
||||||
match bone {
|
|
||||||
PhysicsHandBone::Palm => return None,
|
|
||||||
PhysicsHandBone::Wrist => return None,
|
|
||||||
PhysicsHandBone::ThumbMetacarpal => {
|
|
||||||
return Some((hand_res.thumb.metacarpal, hand_res.thumb.proximal))
|
|
||||||
}
|
|
||||||
PhysicsHandBone::ThumbProximal => {
|
|
||||||
return Some((hand_res.thumb.proximal, hand_res.thumb.distal))
|
|
||||||
}
|
|
||||||
PhysicsHandBone::ThumbDistal => return Some((hand_res.thumb.distal, hand_res.thumb.tip)),
|
|
||||||
PhysicsHandBone::ThumbTip => return None,
|
|
||||||
PhysicsHandBone::IndexMetacarpal => {
|
|
||||||
return Some((hand_res.index.metacarpal, hand_res.index.proximal))
|
|
||||||
}
|
|
||||||
PhysicsHandBone::IndexProximal => {
|
|
||||||
return Some((hand_res.index.proximal, hand_res.index.intermediate))
|
|
||||||
}
|
|
||||||
PhysicsHandBone::IndexIntermediate => {
|
|
||||||
return Some((hand_res.index.intermediate, hand_res.index.distal))
|
|
||||||
}
|
|
||||||
PhysicsHandBone::IndexDistal => return Some((hand_res.index.distal, hand_res.index.tip)),
|
|
||||||
PhysicsHandBone::IndexTip => return None,
|
|
||||||
PhysicsHandBone::MiddleMetacarpal => {
|
|
||||||
return Some((hand_res.middle.metacarpal, hand_res.middle.proximal))
|
|
||||||
}
|
|
||||||
PhysicsHandBone::MiddleProximal => {
|
|
||||||
return Some((hand_res.middle.proximal, hand_res.middle.intermediate))
|
|
||||||
}
|
|
||||||
PhysicsHandBone::MiddleIntermediate => {
|
|
||||||
return Some((hand_res.middle.intermediate, hand_res.middle.distal))
|
|
||||||
}
|
|
||||||
PhysicsHandBone::MiddleDistal => {
|
|
||||||
return Some((hand_res.middle.distal, hand_res.middle.tip))
|
|
||||||
}
|
|
||||||
PhysicsHandBone::MiddleTip => return None,
|
|
||||||
PhysicsHandBone::RingMetacarpal => {
|
|
||||||
return Some((hand_res.ring.metacarpal, hand_res.ring.proximal))
|
|
||||||
}
|
|
||||||
PhysicsHandBone::RingProximal => {
|
|
||||||
return Some((hand_res.ring.proximal, hand_res.ring.intermediate))
|
|
||||||
}
|
|
||||||
PhysicsHandBone::RingIntermediate => {
|
|
||||||
return Some((hand_res.ring.intermediate, hand_res.ring.distal))
|
|
||||||
}
|
|
||||||
PhysicsHandBone::RingDistal => return Some((hand_res.ring.distal, hand_res.ring.tip)),
|
|
||||||
PhysicsHandBone::RingTip => return None,
|
|
||||||
PhysicsHandBone::LittleMetacarpal => {
|
|
||||||
return Some((hand_res.little.metacarpal, hand_res.little.proximal))
|
|
||||||
}
|
|
||||||
PhysicsHandBone::LittleProximal => {
|
|
||||||
return Some((hand_res.little.proximal, hand_res.little.intermediate))
|
|
||||||
}
|
|
||||||
PhysicsHandBone::LittleIntermediate => {
|
|
||||||
return Some((hand_res.little.intermediate, hand_res.little.distal))
|
|
||||||
}
|
|
||||||
PhysicsHandBone::LittleDistal => {
|
|
||||||
return Some((hand_res.little.distal, hand_res.little.tip))
|
|
||||||
}
|
|
||||||
PhysicsHandBone::LittleTip => return None,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_hand_res(res: &Res<'_, HandsResource>, hand: Hand) -> HandResource {
|
|
||||||
match hand {
|
|
||||||
Hand::Left => res.left.clone(),
|
|
||||||
Hand::Right => res.right.clone(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Event, Default)]
|
|
||||||
pub struct SpawnCubeRequest;
|
|
||||||
|
|
||||||
#[derive(Resource)]
|
|
||||||
pub struct SpawnCubeTimer(Timer);
|
|
||||||
|
|
||||||
fn request_cube_spawn(
|
|
||||||
oculus_controller: Res<OculusController>,
|
|
||||||
frame_state: Res<XrFrameState>,
|
|
||||||
xr_input: Res<XrInput>,
|
|
||||||
instance: Res<XrInstance>,
|
|
||||||
session: Res<XrSession>,
|
|
||||||
mut writer: EventWriter<SpawnCubeRequest>,
|
|
||||||
time: Res<Time>,
|
|
||||||
mut timer: ResMut<SpawnCubeTimer>,
|
|
||||||
) {
|
|
||||||
timer.0.tick(time.delta());
|
|
||||||
if timer.0.finished() {
|
|
||||||
//lock frame
|
|
||||||
let frame_state = *frame_state.lock().unwrap();
|
|
||||||
//get controller
|
|
||||||
let controller = oculus_controller.get_ref(&instance, &session, &frame_state, &xr_input);
|
|
||||||
//get controller triggers
|
|
||||||
let left_main_button = controller.a_button();
|
|
||||||
if left_main_button {
|
|
||||||
writer.send(SpawnCubeRequest::default());
|
|
||||||
timer.0.reset();
|
|
||||||
}
|
|
||||||
let right_main_button = controller.x_button();
|
|
||||||
if right_main_button {
|
|
||||||
writer.send(SpawnCubeRequest::default());
|
|
||||||
timer.0.reset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn cube_spawner(
|
|
||||||
mut commands: Commands,
|
|
||||||
mut meshes: ResMut<Assets<Mesh>>,
|
|
||||||
mut materials: ResMut<Assets<StandardMaterial>>,
|
|
||||||
mut events: EventReader<SpawnCubeRequest>,
|
|
||||||
) {
|
|
||||||
for request in events.iter() {
|
|
||||||
// cube
|
|
||||||
commands.spawn((
|
|
||||||
PbrBundle {
|
|
||||||
mesh: meshes.add(Mesh::from(shape::Cube { size: 0.1 })),
|
|
||||||
material: materials.add(Color::rgb(0.8, 0.7, 0.6).into()),
|
|
||||||
transform: Transform::from_xyz(0.0, 1.0, 0.0),
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
RigidBody::Dynamic,
|
|
||||||
Collider::cuboid(0.05, 0.05, 0.05),
|
|
||||||
ColliderDebugColor(Color::hsl(220.0, 1.0, 0.3)),
|
|
||||||
XRInteractable,
|
|
||||||
XRInteractableState::default(),
|
|
||||||
Grabbable,
|
|
||||||
Touched(false),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO: find a real place for this
|
|
||||||
fn prototype_interaction_input(
|
|
||||||
oculus_controller: Res<OculusController>,
|
|
||||||
frame_state: Res<XrFrameState>,
|
|
||||||
xr_input: Res<XrInput>,
|
|
||||||
instance: Res<XrInstance>,
|
|
||||||
session: Res<XrSession>,
|
|
||||||
mut right_interactor_query: Query<
|
|
||||||
(&mut XRInteractorState),
|
|
||||||
(
|
|
||||||
With<XRDirectInteractor>,
|
|
||||||
With<OpenXRRightController>,
|
|
||||||
Without<OpenXRLeftController>,
|
|
||||||
),
|
|
||||||
>,
|
|
||||||
mut left_interactor_query: Query<
|
|
||||||
(&mut XRInteractorState),
|
|
||||||
(
|
|
||||||
With<XRDirectInteractor>,
|
|
||||||
With<OpenXRLeftController>,
|
|
||||||
Without<OpenXRRightController>,
|
|
||||||
),
|
|
||||||
>,
|
|
||||||
) {
|
|
||||||
//lock frame
|
|
||||||
let frame_state = *frame_state.lock().unwrap();
|
|
||||||
//get controller
|
|
||||||
let controller = oculus_controller.get_ref(&instance, &session, &frame_state, &xr_input);
|
|
||||||
//get controller triggers
|
|
||||||
let left_trigger = controller.trigger(Hand::Left);
|
|
||||||
let right_trigger = controller.trigger(Hand::Right);
|
|
||||||
//get the interactors and do state stuff
|
|
||||||
let mut left_state = left_interactor_query.single_mut();
|
|
||||||
if left_trigger > 0.8 {
|
|
||||||
*left_state = XRInteractorState::Selecting;
|
|
||||||
} else {
|
|
||||||
*left_state = XRInteractorState::Idle;
|
|
||||||
}
|
|
||||||
let mut right_state = right_interactor_query.single_mut();
|
|
||||||
if right_trigger > 0.8 {
|
|
||||||
*right_state = XRInteractorState::Selecting;
|
|
||||||
} else {
|
|
||||||
*right_state = XRInteractorState::Idle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Component)]
|
|
||||||
pub struct Grabbable;
|
|
||||||
|
|
||||||
pub fn update_grabbables(
|
|
||||||
mut events: EventReader<InteractionEvent>,
|
|
||||||
mut grabbable_query: Query<(
|
|
||||||
Entity,
|
|
||||||
&mut Transform,
|
|
||||||
With<Grabbable>,
|
|
||||||
Without<XRDirectInteractor>,
|
|
||||||
Option<&mut RigidBody>,
|
|
||||||
)>,
|
|
||||||
mut interactor_query: Query<(
|
|
||||||
&GlobalTransform,
|
|
||||||
&XRInteractorState,
|
|
||||||
&mut XRSelection,
|
|
||||||
Without<Grabbable>,
|
|
||||||
)>,
|
|
||||||
) {
|
|
||||||
//so basically the idea is to try all the events?
|
|
||||||
for event in events.read() {
|
|
||||||
// info!("some event");
|
|
||||||
match grabbable_query.get_mut(event.interactable) {
|
|
||||||
Ok(mut grabbable_transform) => {
|
|
||||||
// info!("we got a grabbable");
|
|
||||||
//now we need the location of our interactor
|
|
||||||
match interactor_query.get_mut(event.interactor) {
|
|
||||||
Ok(mut interactor_transform) => {
|
|
||||||
match *interactor_transform.2 {
|
|
||||||
XRSelection::Empty => {
|
|
||||||
match interactor_transform.1 {
|
|
||||||
XRInteractorState::Idle => match grabbable_transform.4 {
|
|
||||||
Some(mut thing) => {
|
|
||||||
*thing = RigidBody::Dynamic;
|
|
||||||
*interactor_transform.2 = XRSelection::Empty;
|
|
||||||
}
|
|
||||||
None => (),
|
|
||||||
},
|
|
||||||
XRInteractorState::Selecting => {
|
|
||||||
// info!("its a direct interactor?");
|
|
||||||
match grabbable_transform.4 {
|
|
||||||
Some(mut thing) => {
|
|
||||||
*thing = RigidBody::KinematicPositionBased;
|
|
||||||
*interactor_transform.2 =
|
|
||||||
XRSelection::Full(grabbable_transform.0);
|
|
||||||
}
|
|
||||||
None => (),
|
|
||||||
}
|
|
||||||
*grabbable_transform.1 =
|
|
||||||
interactor_transform.0.compute_transform();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
XRSelection::Full(ent) => {
|
|
||||||
info!("nah bro we holding something");
|
|
||||||
match grabbable_transform.0 == ent {
|
|
||||||
true => {
|
|
||||||
*grabbable_transform.1 =
|
|
||||||
interactor_transform.0.compute_transform();
|
|
||||||
}
|
|
||||||
false => {}
|
|
||||||
}
|
|
||||||
match interactor_transform.1 {
|
|
||||||
XRInteractorState::Idle => {
|
|
||||||
*interactor_transform.2 = XRSelection::Empty
|
|
||||||
}
|
|
||||||
XRInteractorState::Selecting => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(_) => {
|
|
||||||
// info!("not a direct interactor")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(_) => {
|
|
||||||
// info!("not a grabbable?")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -56,15 +56,15 @@ pub fn setup_scene(
|
|||||||
));
|
));
|
||||||
|
|
||||||
// light
|
// light
|
||||||
commands.spawn(PointLightBundle {
|
// commands.spawn(PointLightBundle {
|
||||||
point_light: PointLight {
|
// point_light: PointLight {
|
||||||
intensity: 1500.0,
|
// intensity: 1500.0,
|
||||||
shadows_enabled: true,
|
// shadows_enabled: true,
|
||||||
..default()
|
// ..default()
|
||||||
},
|
// },
|
||||||
transform: Transform::from_xyz(4.0, 8.0, 4.0),
|
// transform: Transform::from_xyz(4.0, 8.0, 4.0),
|
||||||
..default()
|
// ..default()
|
||||||
});
|
// });
|
||||||
// camera
|
// camera
|
||||||
commands.spawn((Camera3dBundle {
|
commands.spawn((Camera3dBundle {
|
||||||
transform: Transform::from_xyz(0.25, 1.25, 0.0).looking_at(
|
transform: Transform::from_xyz(0.25, 1.25, 0.0).looking_at(
|
||||||
|
|||||||
@@ -35,10 +35,10 @@ pub fn initialize_xr_graphics(
|
|||||||
vulkan::initialize_xr_graphics(window)
|
vulkan::initialize_xr_graphics(window)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn xr_entry() -> xr::Entry {
|
pub fn xr_entry() -> anyhow::Result<xr::Entry> {
|
||||||
#[cfg(feature = "linked")]
|
#[cfg(feature = "linked")]
|
||||||
let entry = xr::Entry::linked();
|
let entry = Ok(xr::Entry::linked());
|
||||||
#[cfg(not(feature = "linked"))]
|
#[cfg(not(feature = "linked"))]
|
||||||
let entry = unsafe { xr::Entry::load().unwrap() };
|
let entry = unsafe { xr::Entry::load().map_err(|e| anyhow::anyhow!(e)) };
|
||||||
entry
|
entry
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,10 +44,10 @@ pub fn initialize_xr_graphics(
|
|||||||
)> {
|
)> {
|
||||||
use wgpu_hal::{api::Vulkan as V, Api};
|
use wgpu_hal::{api::Vulkan as V, Api};
|
||||||
|
|
||||||
let xr_entry = super::xr_entry();
|
let xr_entry = super::xr_entry()?;
|
||||||
|
|
||||||
#[cfg(target_os = "android")]
|
#[cfg(target_os = "android")]
|
||||||
xr_entry.initialize_android_loader().unwrap();
|
xr_entry.initialize_android_loader()?;
|
||||||
|
|
||||||
let available_extensions = xr_entry.enumerate_extensions()?;
|
let available_extensions = xr_entry.enumerate_extensions()?;
|
||||||
assert!(available_extensions.khr_vulkan_enable2);
|
assert!(available_extensions.khr_vulkan_enable2);
|
||||||
|
|||||||
196
src/lib.rs
196
src/lib.rs
@@ -2,25 +2,41 @@ mod graphics;
|
|||||||
pub mod input;
|
pub mod input;
|
||||||
pub mod resource_macros;
|
pub mod resource_macros;
|
||||||
pub mod resources;
|
pub mod resources;
|
||||||
|
pub mod xr_init;
|
||||||
pub mod xr_input;
|
pub mod xr_input;
|
||||||
|
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
|
use crate::xr_init::RenderRestartPlugin;
|
||||||
use crate::xr_input::hands::hand_tracking::DisableHandTracking;
|
use crate::xr_input::hands::hand_tracking::DisableHandTracking;
|
||||||
use crate::xr_input::oculus_touch::ActionSets;
|
use crate::xr_input::oculus_touch::ActionSets;
|
||||||
use bevy::app::PluginGroupBuilder;
|
use bevy::app::PluginGroupBuilder;
|
||||||
use bevy::ecs::system::SystemState;
|
use bevy::ecs::system::{RunSystemOnce, SystemState};
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy::render::camera::{ManualTextureView, ManualTextureViewHandle, ManualTextureViews};
|
use bevy::render::camera::{
|
||||||
|
CameraPlugin, ManualTextureView, ManualTextureViewHandle, ManualTextureViews,
|
||||||
|
};
|
||||||
|
use bevy::render::globals::GlobalsPlugin;
|
||||||
|
use bevy::render::mesh::morph::MorphPlugin;
|
||||||
|
use bevy::render::mesh::MeshPlugin;
|
||||||
use bevy::render::pipelined_rendering::PipelinedRenderingPlugin;
|
use bevy::render::pipelined_rendering::PipelinedRenderingPlugin;
|
||||||
use bevy::render::renderer::{render_system, RenderInstance};
|
use bevy::render::render_asset::RenderAssetDependency;
|
||||||
|
use bevy::render::render_resource::ShaderLoader;
|
||||||
|
use bevy::render::renderer::{
|
||||||
|
render_system, RenderAdapter, RenderAdapterInfo, RenderDevice, RenderInstance, RenderQueue,
|
||||||
|
};
|
||||||
use bevy::render::settings::RenderCreation;
|
use bevy::render::settings::RenderCreation;
|
||||||
use bevy::render::{Render, RenderApp, RenderPlugin, RenderSet};
|
use bevy::render::view::{self, ViewPlugin, WindowRenderPlugin};
|
||||||
|
use bevy::render::{color, primitives, Render, RenderApp, RenderPlugin, RenderSet};
|
||||||
use bevy::window::{PresentMode, PrimaryWindow, RawHandleWrapper};
|
use bevy::window::{PresentMode, PrimaryWindow, RawHandleWrapper};
|
||||||
use input::XrInput;
|
use input::XrInput;
|
||||||
use openxr as xr;
|
use openxr as xr;
|
||||||
use resources::*;
|
use resources::*;
|
||||||
use xr::FormFactor;
|
use xr::FormFactor;
|
||||||
|
use xr_init::{
|
||||||
|
init_non_xr_graphics, update_xr_stuff, xr_only, RenderCreationData, XrEnableRequest,
|
||||||
|
XrEnableStatus, XrRenderData, XrRenderUpdate,
|
||||||
|
};
|
||||||
use xr_input::controllers::XrControllerType;
|
use xr_input::controllers::XrControllerType;
|
||||||
use xr_input::hands::emulated::HandEmulationPlugin;
|
use xr_input::hands::emulated::HandEmulationPlugin;
|
||||||
use xr_input::hands::hand_tracking::{HandTrackingData, HandTrackingPlugin};
|
use xr_input::hands::hand_tracking::{HandTrackingData, HandTrackingPlugin};
|
||||||
@@ -63,14 +79,10 @@ pub struct FutureXrResources(
|
|||||||
|
|
||||||
impl Plugin for OpenXrPlugin {
|
impl Plugin for OpenXrPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
let future_xr_resources_wrapper = Arc::new(Mutex::new(None));
|
|
||||||
app.insert_resource(FutureXrResources(future_xr_resources_wrapper.clone()));
|
|
||||||
|
|
||||||
let mut system_state: SystemState<Query<&RawHandleWrapper, With<PrimaryWindow>>> =
|
let mut system_state: SystemState<Query<&RawHandleWrapper, With<PrimaryWindow>>> =
|
||||||
SystemState::new(&mut app.world);
|
SystemState::new(&mut app.world);
|
||||||
let primary_window = system_state.get(&app.world).get_single().ok().cloned();
|
let primary_window = system_state.get(&app.world).get_single().ok().cloned();
|
||||||
|
if let Ok((
|
||||||
let (
|
|
||||||
device,
|
device,
|
||||||
queue,
|
queue,
|
||||||
adapter_info,
|
adapter_info,
|
||||||
@@ -87,126 +99,121 @@ impl Plugin for OpenXrPlugin {
|
|||||||
input,
|
input,
|
||||||
views,
|
views,
|
||||||
frame_state,
|
frame_state,
|
||||||
) = graphics::initialize_xr_graphics(primary_window).unwrap();
|
)) = graphics::initialize_xr_graphics(primary_window.clone())
|
||||||
// std::thread::sleep(Duration::from_secs(5));
|
{
|
||||||
debug!("Configured wgpu adapter Limits: {:#?}", device.limits());
|
// std::thread::sleep(Duration::from_secs(5));
|
||||||
debug!("Configured wgpu adapter Features: {:#?}", device.features());
|
debug!("Configured wgpu adapter Limits: {:#?}", device.limits());
|
||||||
let mut future_xr_resources_inner = future_xr_resources_wrapper.lock().unwrap();
|
debug!("Configured wgpu adapter Features: {:#?}", device.features());
|
||||||
*future_xr_resources_inner = Some((
|
app.insert_resource(xr_instance.clone());
|
||||||
xr_instance,
|
app.insert_resource(session.clone());
|
||||||
session,
|
app.insert_resource(blend_mode.clone());
|
||||||
blend_mode,
|
app.insert_resource(resolution.clone());
|
||||||
resolution,
|
app.insert_resource(format.clone());
|
||||||
format,
|
app.insert_resource(session_running.clone());
|
||||||
session_running,
|
app.insert_resource(frame_waiter.clone());
|
||||||
frame_waiter,
|
app.insert_resource(swapchain.clone());
|
||||||
swapchain,
|
app.insert_resource(input.clone());
|
||||||
input,
|
app.insert_resource(views.clone());
|
||||||
views,
|
app.insert_resource(frame_state.clone());
|
||||||
frame_state,
|
let xr_data = XrRenderData {
|
||||||
));
|
xr_instance,
|
||||||
app.insert_resource(ActionSets(vec![]));
|
xr_session: session,
|
||||||
app.add_plugins(RenderPlugin {
|
xr_blend_mode: blend_mode,
|
||||||
render_creation: RenderCreation::Manual(
|
xr_resolution: resolution,
|
||||||
device,
|
xr_format: format,
|
||||||
queue,
|
xr_session_running: session_running,
|
||||||
adapter_info,
|
xr_frame_waiter: frame_waiter,
|
||||||
render_adapter,
|
xr_swapchain: swapchain,
|
||||||
RenderInstance(Arc::new(instance)),
|
xr_input: input,
|
||||||
),
|
xr_views: views,
|
||||||
});
|
xr_frame_state: frame_state,
|
||||||
|
};
|
||||||
|
app.insert_resource(xr_data);
|
||||||
|
app.insert_resource(ActionSets(vec![]));
|
||||||
|
app.add_plugins(RenderPlugin {
|
||||||
|
render_creation: RenderCreation::Manual(
|
||||||
|
device,
|
||||||
|
queue,
|
||||||
|
adapter_info,
|
||||||
|
render_adapter,
|
||||||
|
RenderInstance(Arc::new(instance)),
|
||||||
|
),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
app.add_plugins(RenderPlugin::default());
|
||||||
|
app.insert_resource(XrEnableStatus::Disabled);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ready(&self, app: &App) -> bool {
|
fn ready(&self, app: &App) -> bool {
|
||||||
app.world
|
app.world
|
||||||
.get_resource::<FutureXrResources>()
|
.get_resource::<XrEnableStatus>()
|
||||||
.and_then(|frr| frr.0.try_lock().map(|locked| locked.is_some()).ok())
|
.map(|frr| *frr != XrEnableStatus::Waiting)
|
||||||
.unwrap_or(true)
|
.unwrap_or(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finish(&self, app: &mut App) {
|
fn finish(&self, app: &mut App) {
|
||||||
if let Some(future_renderer_resources) = app.world.remove_resource::<FutureXrResources>() {
|
// TODO: Split this up into the indevidual resources
|
||||||
let (
|
if let Some(data) = app.world.get_resource::<XrRenderData>().cloned() {
|
||||||
xr_instance,
|
// just calling this stuff because I already had the code, so...
|
||||||
session,
|
app.insert_resource(XrEnableStatus::Enabled);
|
||||||
blend_mode,
|
app.world.send_event(XrEnableRequest::TryEnable);
|
||||||
resolution,
|
app.world.run_system_once(update_xr_stuff);
|
||||||
format,
|
app.insert_resource(XrEnableStatus::Enabled);
|
||||||
session_running,
|
//
|
||||||
frame_waiter,
|
let hands = data.xr_instance.exts().ext_hand_tracking.is_some()
|
||||||
swapchain,
|
&& data
|
||||||
input,
|
.xr_instance
|
||||||
views,
|
|
||||||
frame_state,
|
|
||||||
) = future_renderer_resources.0.lock().unwrap().take().unwrap();
|
|
||||||
|
|
||||||
let action_sets = app.world.resource::<ActionSets>().clone();
|
|
||||||
|
|
||||||
app.insert_resource(xr_instance.clone())
|
|
||||||
.insert_resource(session.clone())
|
|
||||||
.insert_resource(blend_mode.clone())
|
|
||||||
.insert_resource(resolution.clone())
|
|
||||||
.insert_resource(format.clone())
|
|
||||||
.insert_resource(session_running.clone())
|
|
||||||
.insert_resource(frame_waiter.clone())
|
|
||||||
.insert_resource(swapchain.clone())
|
|
||||||
.insert_resource(input.clone())
|
|
||||||
.insert_resource(views.clone())
|
|
||||||
.insert_resource(frame_state.clone())
|
|
||||||
.insert_resource(action_sets.clone());
|
|
||||||
let hands = xr_instance.exts().ext_hand_tracking.is_some()
|
|
||||||
&& xr_instance
|
|
||||||
.supports_hand_tracking(
|
.supports_hand_tracking(
|
||||||
xr_instance
|
data.xr_instance
|
||||||
.system(FormFactor::HEAD_MOUNTED_DISPLAY)
|
.system(FormFactor::HEAD_MOUNTED_DISPLAY)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
)
|
||||||
.is_ok_and(|v| v);
|
.is_ok_and(|v| v);
|
||||||
if hands {
|
if hands {
|
||||||
app.insert_resource(HandTrackingData::new(&session).unwrap());
|
app.insert_resource(HandTrackingData::new(&data.xr_session).unwrap());
|
||||||
} else {
|
} else {
|
||||||
app.insert_resource(DisableHandTracking::Both);
|
app.insert_resource(DisableHandTracking::Both);
|
||||||
}
|
}
|
||||||
|
|
||||||
let (left, right) = swapchain.get_render_views();
|
let (left, right) = data.xr_swapchain.get_render_views();
|
||||||
let left = ManualTextureView {
|
let left = ManualTextureView {
|
||||||
texture_view: left.into(),
|
texture_view: left.into(),
|
||||||
size: *resolution,
|
size: *data.xr_resolution,
|
||||||
format: *format,
|
format: *data.xr_format,
|
||||||
};
|
};
|
||||||
let right = ManualTextureView {
|
let right = ManualTextureView {
|
||||||
texture_view: right.into(),
|
texture_view: right.into(),
|
||||||
size: *resolution,
|
size: *data.xr_resolution,
|
||||||
format: *format,
|
format: *data.xr_format,
|
||||||
};
|
};
|
||||||
app.add_systems(PreUpdate, xr_begin_frame);
|
app.add_systems(PreUpdate, xr_begin_frame.run_if(xr_only()));
|
||||||
let mut manual_texture_views = app.world.resource_mut::<ManualTextureViews>();
|
let mut manual_texture_views = app.world.resource_mut::<ManualTextureViews>();
|
||||||
manual_texture_views.insert(LEFT_XR_TEXTURE_HANDLE, left);
|
manual_texture_views.insert(LEFT_XR_TEXTURE_HANDLE, left);
|
||||||
manual_texture_views.insert(RIGHT_XR_TEXTURE_HANDLE, right);
|
manual_texture_views.insert(RIGHT_XR_TEXTURE_HANDLE, right);
|
||||||
drop(manual_texture_views);
|
drop(manual_texture_views);
|
||||||
let render_app = app.sub_app_mut(RenderApp);
|
let render_app = app.sub_app_mut(RenderApp);
|
||||||
|
|
||||||
render_app
|
render_app.insert_resource(data.xr_instance.clone());
|
||||||
.insert_resource(xr_instance)
|
render_app.insert_resource(data.xr_session.clone());
|
||||||
.insert_resource(session)
|
render_app.insert_resource(data.xr_blend_mode.clone());
|
||||||
.insert_resource(blend_mode)
|
render_app.insert_resource(data.xr_resolution.clone());
|
||||||
.insert_resource(resolution)
|
render_app.insert_resource(data.xr_format.clone());
|
||||||
.insert_resource(format)
|
render_app.insert_resource(data.xr_session_running.clone());
|
||||||
.insert_resource(session_running)
|
render_app.insert_resource(data.xr_frame_waiter.clone());
|
||||||
.insert_resource(frame_waiter)
|
render_app.insert_resource(data.xr_swapchain.clone());
|
||||||
.insert_resource(swapchain)
|
render_app.insert_resource(data.xr_input.clone());
|
||||||
.insert_resource(input)
|
render_app.insert_resource(data.xr_views.clone());
|
||||||
.insert_resource(views)
|
render_app.insert_resource(data.xr_frame_state.clone());
|
||||||
.insert_resource(frame_state)
|
render_app.insert_resource(XrEnableStatus::Enabled);
|
||||||
.insert_resource(action_sets);
|
|
||||||
|
|
||||||
render_app.add_systems(
|
render_app.add_systems(
|
||||||
Render,
|
Render,
|
||||||
(
|
(
|
||||||
post_frame
|
post_frame
|
||||||
|
.run_if(xr_only())
|
||||||
.before(render_system)
|
.before(render_system)
|
||||||
.after(RenderSet::ExtractCommands),
|
.after(RenderSet::ExtractCommands),
|
||||||
end_frame.after(render_system),
|
end_frame.run_if(xr_only()).after(render_system),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -221,8 +228,9 @@ impl PluginGroup for DefaultXrPlugins {
|
|||||||
.build()
|
.build()
|
||||||
.disable::<RenderPlugin>()
|
.disable::<RenderPlugin>()
|
||||||
.disable::<PipelinedRenderingPlugin>()
|
.disable::<PipelinedRenderingPlugin>()
|
||||||
.add_before::<RenderPlugin, _>(OpenXrPlugin::default())
|
.add_before::<RenderPlugin, _>(OpenXrPlugin)
|
||||||
.add_after::<OpenXrPlugin, _>(OpenXrInput::new(XrControllerType::OculusTouch))
|
.add_after::<OpenXrPlugin, _>(OpenXrInput::new(XrControllerType::OculusTouch))
|
||||||
|
.add_before::<OpenXrPlugin, _>(RenderRestartPlugin)
|
||||||
.add(HandEmulationPlugin)
|
.add(HandEmulationPlugin)
|
||||||
.add(HandTrackingPlugin)
|
.add(HandTrackingPlugin)
|
||||||
.set(WindowPlugin {
|
.set(WindowPlugin {
|
||||||
|
|||||||
354
src/xr_init.rs
Normal file
354
src/xr_init.rs
Normal file
@@ -0,0 +1,354 @@
|
|||||||
|
// Just a lot of code that is meant for something way more complex but hey.
|
||||||
|
// maybe will work on that soon
|
||||||
|
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use bevy::{
|
||||||
|
ecs::schedule::{ExecutorKind, ScheduleLabel},
|
||||||
|
prelude::*,
|
||||||
|
render::{
|
||||||
|
extract_resource::{ExtractResource, ExtractResourcePlugin},
|
||||||
|
renderer::{
|
||||||
|
self, RenderAdapter, RenderAdapterInfo, RenderDevice, RenderInstance, RenderQueue,
|
||||||
|
},
|
||||||
|
settings::WgpuSettings,
|
||||||
|
},
|
||||||
|
window::{PrimaryWindow, RawHandleWrapper},
|
||||||
|
};
|
||||||
|
use wgpu::Instance;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
graphics,
|
||||||
|
input::XrInput,
|
||||||
|
resources::{
|
||||||
|
XrEnvironmentBlendMode, XrFormat, XrFrameState, XrFrameWaiter, XrInstance, XrResolution,
|
||||||
|
XrSession, XrSessionRunning, XrSwapchain, XrViews,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Resource, Clone)]
|
||||||
|
pub struct RenderCreationData {
|
||||||
|
pub device: RenderDevice,
|
||||||
|
pub queue: RenderQueue,
|
||||||
|
pub adapter_info: RenderAdapterInfo,
|
||||||
|
pub render_adapter: RenderAdapter,
|
||||||
|
pub instance: Arc<Instance>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Resource, Clone, ExtractResource)]
|
||||||
|
pub struct XrRenderData {
|
||||||
|
pub xr_instance: XrInstance,
|
||||||
|
pub xr_session: XrSession,
|
||||||
|
pub xr_blend_mode: XrEnvironmentBlendMode,
|
||||||
|
pub xr_resolution: XrResolution,
|
||||||
|
pub xr_format: XrFormat,
|
||||||
|
pub xr_session_running: XrSessionRunning,
|
||||||
|
pub xr_frame_waiter: XrFrameWaiter,
|
||||||
|
pub xr_swapchain: XrSwapchain,
|
||||||
|
pub xr_input: XrInput,
|
||||||
|
pub xr_views: XrViews,
|
||||||
|
pub xr_frame_state: XrFrameState,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Event, Clone, Copy, Debug)]
|
||||||
|
pub enum XrEnableRequest {
|
||||||
|
TryEnable,
|
||||||
|
TryDisable,
|
||||||
|
}
|
||||||
|
#[derive(Resource, Event, Copy, Clone, PartialEq, Eq)]
|
||||||
|
pub enum XrEnableStatus {
|
||||||
|
Enabled,
|
||||||
|
Disabled,
|
||||||
|
Waiting,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Resource, Event, Copy, Clone, PartialEq, Eq, Debug)]
|
||||||
|
pub enum XrNextEnabledState {
|
||||||
|
Enabled,
|
||||||
|
Disabled,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct RenderRestartPlugin;
|
||||||
|
|
||||||
|
#[derive(Resource)]
|
||||||
|
pub struct ForceMain;
|
||||||
|
|
||||||
|
#[derive(Debug, ScheduleLabel, Clone, Copy, Hash, PartialEq, Eq)]
|
||||||
|
pub struct XrPreSetup;
|
||||||
|
#[derive(Debug, ScheduleLabel, Clone, Copy, Hash, PartialEq, Eq)]
|
||||||
|
pub struct XrSetup;
|
||||||
|
#[derive(Debug, ScheduleLabel, Clone, Copy, Hash, PartialEq, Eq)]
|
||||||
|
pub struct XrPrePostSetup;
|
||||||
|
#[derive(Debug, ScheduleLabel, Clone, Copy, Hash, PartialEq, Eq)]
|
||||||
|
pub struct XrPostSetup;
|
||||||
|
|
||||||
|
#[derive(Debug, ScheduleLabel, Clone, Copy, Hash, PartialEq, Eq)]
|
||||||
|
pub struct XrPreCleanup;
|
||||||
|
#[derive(Debug, ScheduleLabel, Clone, Copy, Hash, PartialEq, Eq)]
|
||||||
|
pub struct XrCleanup;
|
||||||
|
#[derive(Debug, ScheduleLabel, Clone, Copy, Hash, PartialEq, Eq)]
|
||||||
|
pub struct XrPostCleanup;
|
||||||
|
|
||||||
|
#[derive(Debug, ScheduleLabel, Clone, Copy, Hash, PartialEq, Eq)]
|
||||||
|
pub struct XrPreRenderUpdate;
|
||||||
|
#[derive(Debug, ScheduleLabel, Clone, Copy, Hash, PartialEq, Eq)]
|
||||||
|
pub struct XrRenderUpdate;
|
||||||
|
#[derive(Debug, ScheduleLabel, Clone, Copy, Hash, PartialEq, Eq)]
|
||||||
|
pub struct XrPostRenderUpdate;
|
||||||
|
|
||||||
|
pub fn xr_only() -> impl FnMut(Option<Res<'_, XrEnableStatus>>) -> bool {
|
||||||
|
resource_exists_and_equals(XrEnableStatus::Enabled)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Plugin for RenderRestartPlugin {
|
||||||
|
fn build(&self, app: &mut App) {
|
||||||
|
add_schedules(app);
|
||||||
|
app.add_plugins(ExtractResourcePlugin::<XrRenderData>::default())
|
||||||
|
.insert_resource(ForceMain)
|
||||||
|
.add_event::<XrEnableRequest>()
|
||||||
|
.add_event::<XrEnableStatus>()
|
||||||
|
.add_systems(
|
||||||
|
PostUpdate,
|
||||||
|
update_xr_stuff.run_if(on_event::<XrEnableRequest>()),
|
||||||
|
)
|
||||||
|
.add_systems(XrPreRenderUpdate, decide_next_xr_state)
|
||||||
|
.add_systems(XrPostRenderUpdate, clear_events)
|
||||||
|
.add_systems(
|
||||||
|
XrRenderUpdate,
|
||||||
|
(
|
||||||
|
cleanup_xr.run_if(resource_exists_and_equals(XrNextEnabledState::Disabled)),
|
||||||
|
// handle_xr_enable_requests,
|
||||||
|
apply_deferred,
|
||||||
|
setup_xr/* .run_if(resource_exists_and_equals(XrEnableStatus::Enabled)) */,
|
||||||
|
)
|
||||||
|
.chain(),
|
||||||
|
)
|
||||||
|
.add_systems(XrCleanup, cleanup_oxr_session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn clear_events(mut events: ResMut<Events<XrEnableRequest>>) {
|
||||||
|
events.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_schedules(app: &mut App) {
|
||||||
|
let schedules = [
|
||||||
|
Schedule::new(XrPreSetup),
|
||||||
|
Schedule::new(XrSetup),
|
||||||
|
Schedule::new(XrPrePostSetup),
|
||||||
|
Schedule::new(XrPostSetup),
|
||||||
|
Schedule::new(XrPreRenderUpdate),
|
||||||
|
Schedule::new(XrRenderUpdate),
|
||||||
|
Schedule::new(XrPostRenderUpdate),
|
||||||
|
Schedule::new(XrPreCleanup),
|
||||||
|
Schedule::new(XrCleanup),
|
||||||
|
Schedule::new(XrPostCleanup),
|
||||||
|
];
|
||||||
|
for mut schedule in schedules {
|
||||||
|
schedule.set_executor_kind(ExecutorKind::SingleThreaded);
|
||||||
|
schedule.set_apply_final_deferred(true);
|
||||||
|
app.add_schedule(schedule);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup_xr(world: &mut World) {
|
||||||
|
world.run_schedule(XrPreSetup);
|
||||||
|
info!("PreSetup Done");
|
||||||
|
world.run_schedule(XrSetup);
|
||||||
|
info!("Setup Done");
|
||||||
|
world.run_schedule(XrPrePostSetup);
|
||||||
|
info!("PrePostSetup Done");
|
||||||
|
world.run_schedule(XrPostSetup);
|
||||||
|
info!("PostSetup Done");
|
||||||
|
}
|
||||||
|
fn cleanup_xr(world: &mut World) {
|
||||||
|
world.run_schedule(XrPreCleanup);
|
||||||
|
world.run_schedule(XrCleanup);
|
||||||
|
world.run_schedule(XrPostCleanup);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cleanup_oxr_session(xr_status: Option<Res<XrEnableStatus>>, session: Option<ResMut<XrSession>>) {
|
||||||
|
if let (Some(XrEnableStatus::Disabled), Some(s)) = (xr_status.map(|v| v.into_inner()), session)
|
||||||
|
{
|
||||||
|
s.into_inner().request_exit().unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update_xr_stuff(world: &mut World) {
|
||||||
|
world.run_schedule(XrPreRenderUpdate);
|
||||||
|
world.run_schedule(XrRenderUpdate);
|
||||||
|
world.run_schedule(XrPostRenderUpdate);
|
||||||
|
}
|
||||||
|
|
||||||
|
// fn handle_xr_enable_requests(
|
||||||
|
// primary_window: Query<&RawHandleWrapper, With<PrimaryWindow>>,
|
||||||
|
// mut commands: Commands,
|
||||||
|
// next_state: Res<XrNextEnabledState>,
|
||||||
|
// on_main: Option<NonSend<ForceMain>>,
|
||||||
|
// ) {
|
||||||
|
// // Just to force this system onto the main thread because of unsafe code
|
||||||
|
// let _ = on_main;
|
||||||
|
//
|
||||||
|
// commands.insert_resource(XrEnableStatus::Waiting);
|
||||||
|
// let (creation_data, xr_data) = match next_state.into_inner() {
|
||||||
|
// XrNextEnabledState::Enabled => {
|
||||||
|
// let (
|
||||||
|
// device,
|
||||||
|
// queue,
|
||||||
|
// adapter_info,
|
||||||
|
// render_adapter,
|
||||||
|
// instance,
|
||||||
|
// xr_instance,
|
||||||
|
// session,
|
||||||
|
// blend_mode,
|
||||||
|
// resolution,
|
||||||
|
// format,
|
||||||
|
// session_running,
|
||||||
|
// frame_waiter,
|
||||||
|
// swapchain,
|
||||||
|
// input,
|
||||||
|
// views,
|
||||||
|
// frame_state,
|
||||||
|
// ) = graphics::initialize_xr_graphics(primary_window.get_single().ok().cloned())
|
||||||
|
// .unwrap();
|
||||||
|
//
|
||||||
|
// commands.insert_resource(XrEnableStatus::Enabled);
|
||||||
|
// (
|
||||||
|
// RenderCreationData {
|
||||||
|
// device,
|
||||||
|
// queue,
|
||||||
|
// adapter_info,
|
||||||
|
// render_adapter,
|
||||||
|
// instance: Arc::new(instance),
|
||||||
|
// },
|
||||||
|
// Some(XrRenderData {
|
||||||
|
// xr_instance,
|
||||||
|
// xr_session: session,
|
||||||
|
// xr_blend_mode: blend_mode,
|
||||||
|
// xr_resolution: resolution,
|
||||||
|
// xr_format: format,
|
||||||
|
// xr_session_running: session_running,
|
||||||
|
// xr_frame_waiter: frame_waiter,
|
||||||
|
// xr_swapchain: swapchain,
|
||||||
|
// xr_input: input,
|
||||||
|
// xr_views: views,
|
||||||
|
// xr_frame_state: frame_state,
|
||||||
|
// }),
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
// XrNextEnabledState::Disabled => (
|
||||||
|
// init_non_xr_graphics(primary_window.get_single().ok().cloned()),
|
||||||
|
// None,
|
||||||
|
// ),
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// commands.insert_resource(creation_data.device);
|
||||||
|
// commands.insert_resource(creation_data.queue);
|
||||||
|
// commands.insert_resource(RenderInstance(creation_data.instance));
|
||||||
|
// commands.insert_resource(creation_data.adapter_info);
|
||||||
|
// commands.insert_resource(creation_data.render_adapter);
|
||||||
|
//
|
||||||
|
// if let Some(xr_data) = xr_data {
|
||||||
|
// // TODO: Remove this lib.rs:144
|
||||||
|
// commands.insert_resource(xr_data.clone());
|
||||||
|
//
|
||||||
|
// commands.insert_resource(xr_data.xr_instance);
|
||||||
|
// commands.insert_resource(xr_data.xr_session);
|
||||||
|
// commands.insert_resource(xr_data.xr_blend_mode);
|
||||||
|
// commands.insert_resource(xr_data.xr_resolution);
|
||||||
|
// commands.insert_resource(xr_data.xr_format);
|
||||||
|
// commands.insert_resource(xr_data.xr_session_running);
|
||||||
|
// commands.insert_resource(xr_data.xr_frame_waiter);
|
||||||
|
// commands.insert_resource(xr_data.xr_input);
|
||||||
|
// commands.insert_resource(xr_data.xr_views);
|
||||||
|
// commands.insert_resource(xr_data.xr_frame_state);
|
||||||
|
// commands.insert_resource(xr_data.xr_swapchain);
|
||||||
|
// } else {
|
||||||
|
// commands.remove_resource::<XrRenderData>();
|
||||||
|
//
|
||||||
|
// commands.remove_resource::<XrInstance>();
|
||||||
|
// commands.remove_resource::<XrSession>();
|
||||||
|
// commands.remove_resource::<XrEnvironmentBlendMode>();
|
||||||
|
// commands.remove_resource::<XrResolution>();
|
||||||
|
// commands.remove_resource::<XrFormat>();
|
||||||
|
// commands.remove_resource::<XrSessionRunning>();
|
||||||
|
// commands.remove_resource::<XrFrameWaiter>();
|
||||||
|
// commands.remove_resource::<XrSwapchain>();
|
||||||
|
// commands.remove_resource::<XrInput>();
|
||||||
|
// commands.remove_resource::<XrViews>();
|
||||||
|
// commands.remove_resource::<XrFrameState>();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
fn decide_next_xr_state(
|
||||||
|
mut commands: Commands,
|
||||||
|
mut events: EventReader<XrEnableRequest>,
|
||||||
|
xr_status: Option<Res<XrEnableStatus>>,
|
||||||
|
) {
|
||||||
|
info!("hm");
|
||||||
|
let request = match events.read().next() {
|
||||||
|
Some(v) => v,
|
||||||
|
None => return,
|
||||||
|
};
|
||||||
|
info!("ok");
|
||||||
|
match (request, xr_status.as_deref()) {
|
||||||
|
(XrEnableRequest::TryEnable, Some(XrEnableStatus::Enabled)) => {
|
||||||
|
info!("Xr Already Enabled! ignoring request");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
(XrEnableRequest::TryDisable, Some(XrEnableStatus::Disabled)) => {
|
||||||
|
info!("Xr Already Disabled! ignoring request");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
(_, Some(XrEnableStatus::Waiting)) => {
|
||||||
|
info!("Already Handling Request! ignoring request");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
let r = match request {
|
||||||
|
XrEnableRequest::TryEnable => XrNextEnabledState::Enabled,
|
||||||
|
XrEnableRequest::TryDisable => XrNextEnabledState::Disabled,
|
||||||
|
};
|
||||||
|
info!("{:#?}", r);
|
||||||
|
commands.insert_resource(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn init_non_xr_graphics(primary_window: Option<RawHandleWrapper>) -> RenderCreationData {
|
||||||
|
let settings = WgpuSettings::default();
|
||||||
|
|
||||||
|
let async_renderer = async move {
|
||||||
|
let instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
|
||||||
|
// Probably a bad idea unwraping here but on the other hand no backends
|
||||||
|
backends: settings.backends.unwrap(),
|
||||||
|
dx12_shader_compiler: settings.dx12_shader_compiler.clone(),
|
||||||
|
});
|
||||||
|
let surface = primary_window.map(|wrapper| unsafe {
|
||||||
|
// SAFETY: Plugins should be set up on the main thread.
|
||||||
|
let handle = wrapper.get_handle();
|
||||||
|
instance
|
||||||
|
.create_surface(&handle)
|
||||||
|
.expect("Failed to create wgpu surface")
|
||||||
|
});
|
||||||
|
|
||||||
|
let request_adapter_options = wgpu::RequestAdapterOptions {
|
||||||
|
power_preference: settings.power_preference,
|
||||||
|
compatible_surface: surface.as_ref(),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
let (device, queue, adapter_info, render_adapter) =
|
||||||
|
renderer::initialize_renderer(&instance, &settings, &request_adapter_options).await;
|
||||||
|
debug!("Configured wgpu adapter Limits: {:#?}", device.limits());
|
||||||
|
debug!("Configured wgpu adapter Features: {:#?}", device.features());
|
||||||
|
RenderCreationData {
|
||||||
|
device,
|
||||||
|
queue,
|
||||||
|
adapter_info,
|
||||||
|
render_adapter,
|
||||||
|
instance: Arc::new(instance),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// No need for wasm in bevy_oxr web xr would be a different crate
|
||||||
|
futures_lite::future::block_on(async_renderer)
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@ use bevy::{prelude::*, utils::HashMap};
|
|||||||
use openxr as xr;
|
use openxr as xr;
|
||||||
use xr::{Action, Binding, Haptic, Posef};
|
use xr::{Action, Binding, Haptic, Posef};
|
||||||
|
|
||||||
use crate::resources::{XrInstance, XrSession};
|
use crate::{resources::{XrInstance, XrSession}, xr_init::XrPrePostSetup};
|
||||||
|
|
||||||
use super::oculus_touch::ActionSets;
|
use super::oculus_touch::ActionSets;
|
||||||
|
|
||||||
@@ -12,11 +12,12 @@ impl Plugin for OpenXrActionsPlugin {
|
|||||||
app.insert_resource(SetupActionSets {
|
app.insert_resource(SetupActionSets {
|
||||||
sets: HashMap::new(),
|
sets: HashMap::new(),
|
||||||
});
|
});
|
||||||
app.add_systems(PostStartup, setup_oxr_actions);
|
app.add_systems(XrPrePostSetup, setup_oxr_actions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setup_oxr_actions(world: &mut World) {
|
pub fn setup_oxr_actions(world: &mut World) {
|
||||||
|
info!("huh?!");
|
||||||
let actions = world.remove_resource::<SetupActionSets>().unwrap();
|
let actions = world.remove_resource::<SetupActionSets>().unwrap();
|
||||||
let instance = world.get_resource::<XrInstance>().unwrap();
|
let instance = world.get_resource::<XrInstance>().unwrap();
|
||||||
let session = world.get_resource::<XrSession>().unwrap();
|
let session = world.get_resource::<XrSession>().unwrap();
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
|
use bevy::ecs::schedule::IntoSystemConfigs;
|
||||||
use bevy::log::{debug, info};
|
use bevy::log::{debug, info};
|
||||||
use bevy::prelude::{
|
use bevy::prelude::{
|
||||||
Color, Gizmos, GlobalTransform, Plugin, Quat, Query, Res, Transform, Update, Vec2, Vec3, With,
|
Color, Gizmos, GlobalTransform, Plugin, Quat, Query, Res, Transform, Update, Vec2, Vec3, With,
|
||||||
Without,
|
Without,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::xr_init::xr_only;
|
||||||
use crate::{
|
use crate::{
|
||||||
input::XrInput,
|
input::XrInput,
|
||||||
resources::{XrFrameState, XrSession},
|
resources::{XrFrameState, XrSession},
|
||||||
@@ -25,34 +27,41 @@ pub struct OpenXrDebugRenderer;
|
|||||||
|
|
||||||
impl Plugin for OpenXrDebugRenderer {
|
impl Plugin for OpenXrDebugRenderer {
|
||||||
fn build(&self, app: &mut bevy::prelude::App) {
|
fn build(&self, app: &mut bevy::prelude::App) {
|
||||||
app.add_systems(Update, draw_gizmos);
|
app.add_systems(Update, draw_gizmos.run_if(xr_only()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_arguments, clippy::complexity)]
|
||||||
pub fn draw_gizmos(
|
pub fn draw_gizmos(
|
||||||
mut gizmos: Gizmos,
|
mut gizmos: Gizmos,
|
||||||
oculus_controller: Res<OculusController>,
|
oculus_controller: Res<OculusController>,
|
||||||
frame_state: Res<XrFrameState>,
|
frame_state: Res<XrFrameState>,
|
||||||
xr_input: Res<XrInput>,
|
xr_input: Res<XrInput>,
|
||||||
session: Res<XrSession>,
|
session: Res<XrSession>,
|
||||||
tracking_root_query: Query<(
|
tracking_root_query: Query<
|
||||||
&mut Transform,
|
&mut Transform,
|
||||||
With<OpenXRTrackingRoot>,
|
(
|
||||||
Without<OpenXRLeftController>,
|
With<OpenXRTrackingRoot>,
|
||||||
Without<OpenXRRightController>,
|
Without<OpenXRLeftController>,
|
||||||
)>,
|
Without<OpenXRRightController>,
|
||||||
left_controller_query: Query<(
|
),
|
||||||
|
>,
|
||||||
|
left_controller_query: Query<
|
||||||
&GlobalTransform,
|
&GlobalTransform,
|
||||||
With<OpenXRLeftController>,
|
(
|
||||||
Without<OpenXRRightController>,
|
With<OpenXRLeftController>,
|
||||||
Without<OpenXRTrackingRoot>,
|
Without<OpenXRRightController>,
|
||||||
)>,
|
Without<OpenXRTrackingRoot>,
|
||||||
right_controller_query: Query<(
|
),
|
||||||
|
>,
|
||||||
|
right_controller_query: Query<
|
||||||
&GlobalTransform,
|
&GlobalTransform,
|
||||||
With<OpenXRRightController>,
|
(
|
||||||
Without<OpenXRLeftController>,
|
With<OpenXRRightController>,
|
||||||
Without<OpenXRTrackingRoot>,
|
Without<OpenXRLeftController>,
|
||||||
)>,
|
Without<OpenXRTrackingRoot>,
|
||||||
|
),
|
||||||
|
>,
|
||||||
action_sets: Res<XrActionSets>,
|
action_sets: Res<XrActionSets>,
|
||||||
) {
|
) {
|
||||||
// if let Some(hand_tracking) = hand_tracking {
|
// if let Some(hand_tracking) = hand_tracking {
|
||||||
@@ -89,7 +98,7 @@ pub fn draw_gizmos(
|
|||||||
match root {
|
match root {
|
||||||
Ok(position) => {
|
Ok(position) => {
|
||||||
gizmos.circle(
|
gizmos.circle(
|
||||||
position.0.translation
|
position.translation
|
||||||
+ Vec3 {
|
+ Vec3 {
|
||||||
x: 0.0,
|
x: 0.0,
|
||||||
y: 0.01,
|
y: 0.01,
|
||||||
@@ -107,7 +116,7 @@ pub fn draw_gizmos(
|
|||||||
let left_transform = left_controller_query.get_single();
|
let left_transform = left_controller_query.get_single();
|
||||||
match left_transform {
|
match left_transform {
|
||||||
Ok(left_entity) => {
|
Ok(left_entity) => {
|
||||||
draw_hand_gizmo(&mut gizmos, &controller, Hand::Left, left_entity.0);
|
draw_hand_gizmo(&mut gizmos, &controller, Hand::Left, left_entity);
|
||||||
}
|
}
|
||||||
Err(_) => debug!("no left controller entity for debug gizmos"),
|
Err(_) => debug!("no left controller entity for debug gizmos"),
|
||||||
}
|
}
|
||||||
@@ -115,7 +124,7 @@ pub fn draw_gizmos(
|
|||||||
let right_transform = right_controller_query.get_single();
|
let right_transform = right_controller_query.get_single();
|
||||||
match right_transform {
|
match right_transform {
|
||||||
Ok(right_entity) => {
|
Ok(right_entity) => {
|
||||||
draw_hand_gizmo(&mut gizmos, &controller, Hand::Right, right_entity.0);
|
draw_hand_gizmo(&mut gizmos, &controller, Hand::Right, right_entity);
|
||||||
}
|
}
|
||||||
Err(_) => debug!("no right controller entity for debug gizmos"),
|
Err(_) => debug!("no right controller entity for debug gizmos"),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ use openxr::{ActionTy, HandJoint};
|
|||||||
|
|
||||||
use super::common::{get_bone_gizmo_style, HandBoneRadius};
|
use super::common::{get_bone_gizmo_style, HandBoneRadius};
|
||||||
use crate::{
|
use crate::{
|
||||||
|
xr_init::{xr_only, XrSetup},
|
||||||
resources::{XrInstance, XrSession},
|
resources::{XrInstance, XrSession},
|
||||||
xr_input::{
|
xr_input::{
|
||||||
actions::{
|
actions::{
|
||||||
@@ -27,8 +28,11 @@ pub struct HandEmulationPlugin;
|
|||||||
|
|
||||||
impl Plugin for HandEmulationPlugin {
|
impl Plugin for HandEmulationPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.add_systems(PreUpdate, update_hand_skeleton_from_emulated);
|
app.add_systems(
|
||||||
app.add_systems(Startup, setup_hand_emulation_action_set);
|
Update,
|
||||||
|
update_hand_skeleton_from_emulated.run_if(xr_only()),
|
||||||
|
);
|
||||||
|
app.add_systems(XrSetup, setup_hand_emulation_action_set);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,7 +91,7 @@ fn setup_hand_emulation_action_set(mut action_sets: ResMut<SetupActionSets>) {
|
|||||||
ActionHandednes::Double,
|
ActionHandednes::Double,
|
||||||
);
|
);
|
||||||
|
|
||||||
suggest_oculus_touch_profile(&mut action_set);
|
suggest_oculus_touch_profile(action_set);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct EmulatedHandPoseData {}
|
pub struct EmulatedHandPoseData {}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use crate::{
|
|||||||
xr_input::{
|
xr_input::{
|
||||||
hands::HandBone, trackers::OpenXRTrackingRoot, Hand, QuatConv,
|
hands::HandBone, trackers::OpenXRTrackingRoot, Hand, QuatConv,
|
||||||
Vec3Conv,
|
Vec3Conv,
|
||||||
},
|
}, xr_init::xr_only,
|
||||||
};
|
};
|
||||||
use super::common::HandBoneRadius;
|
use super::common::HandBoneRadius;
|
||||||
|
|
||||||
@@ -128,7 +128,7 @@ impl Plugin for HandTrackingPlugin {
|
|||||||
(
|
(
|
||||||
update_hand_bones.run_if(|dh: Option<Res<DisableHandTracking>>| {
|
update_hand_bones.run_if(|dh: Option<Res<DisableHandTracking>>| {
|
||||||
!dh.is_some_and(|v| *v == DisableHandTracking::Both)
|
!dh.is_some_and(|v| *v == DisableHandTracking::Both)
|
||||||
}),
|
}).run_if(xr_only()),
|
||||||
update_tracking_state_on_disable,
|
update_tracking_state_on_disable,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -9,13 +9,14 @@ pub mod prototype_locomotion;
|
|||||||
pub mod trackers;
|
pub mod trackers;
|
||||||
pub mod xr_camera;
|
pub mod xr_camera;
|
||||||
|
|
||||||
|
use crate::xr_init::{XrPostSetup, XrSetup, xr_only};
|
||||||
use crate::resources::{XrInstance, XrSession};
|
use crate::resources::{XrInstance, XrSession};
|
||||||
use crate::xr_begin_frame;
|
use crate::xr_begin_frame;
|
||||||
use crate::xr_input::controllers::XrControllerType;
|
use crate::xr_input::controllers::XrControllerType;
|
||||||
use crate::xr_input::oculus_touch::setup_oculus_controller;
|
use crate::xr_input::oculus_touch::setup_oculus_controller;
|
||||||
use crate::xr_input::xr_camera::{xr_camera_head_sync, Eye, XRProjection, XrCameraBundle};
|
use crate::xr_input::xr_camera::{xr_camera_head_sync, Eye, XRProjection, XrCameraBundle};
|
||||||
use bevy::app::{App, PostUpdate, Startup};
|
use bevy::app::{App, PostUpdate, Startup};
|
||||||
use bevy::log::warn;
|
use bevy::log::{warn, info};
|
||||||
use bevy::prelude::{BuildChildren, Component, Deref, DerefMut, IntoSystemConfigs, Resource};
|
use bevy::prelude::{BuildChildren, Component, Deref, DerefMut, IntoSystemConfigs, Resource};
|
||||||
use bevy::prelude::{Commands, Plugin, PreUpdate, Quat, Res, SpatialBundle, Update, Vec3};
|
use bevy::prelude::{Commands, Plugin, PreUpdate, Quat, Res, SpatialBundle, Update, Vec3};
|
||||||
use bevy::render::camera::CameraProjectionPlugin;
|
use bevy::render::camera::CameraProjectionPlugin;
|
||||||
@@ -52,27 +53,27 @@ impl Plugin for OpenXrInput {
|
|||||||
app.add_plugins(CameraProjectionPlugin::<XRProjection>::default());
|
app.add_plugins(CameraProjectionPlugin::<XRProjection>::default());
|
||||||
app.add_plugins(OpenXrActionsPlugin);
|
app.add_plugins(OpenXrActionsPlugin);
|
||||||
app.add_systems(
|
app.add_systems(
|
||||||
PreUpdate,
|
XrPostSetup,
|
||||||
(post_action_setup_oculus_controller.after(setup_oxr_actions),),
|
post_action_setup_oculus_controller,
|
||||||
);
|
);
|
||||||
match self.controller_type {
|
match self.controller_type {
|
||||||
XrControllerType::OculusTouch => {
|
XrControllerType::OculusTouch => {
|
||||||
app.add_systems(Startup, setup_oculus_controller);
|
app.add_systems(XrSetup, setup_oculus_controller);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//adopt any new trackers
|
//adopt any new trackers
|
||||||
app.add_systems(PreUpdate, adopt_open_xr_trackers);
|
app.add_systems(PreUpdate, adopt_open_xr_trackers.run_if(xr_only()));
|
||||||
app.add_systems(PreUpdate, action_set_system);
|
// app.add_systems(PreUpdate, action_set_system);
|
||||||
app.add_systems(PreUpdate, xr_camera_head_sync.after(xr_begin_frame));
|
app.add_systems(PreUpdate, xr_camera_head_sync.run_if(xr_only()).after(xr_begin_frame));
|
||||||
//update controller trackers
|
//update controller trackers
|
||||||
app.add_systems(Update, update_open_xr_controllers);
|
app.add_systems(Update, update_open_xr_controllers.run_if(xr_only()));
|
||||||
app.add_systems(
|
app.add_systems(
|
||||||
PostUpdate,
|
PostUpdate,
|
||||||
update_frusta::<XRProjection>
|
update_frusta::<XRProjection>
|
||||||
.after(TransformSystem::TransformPropagate)
|
.after(TransformSystem::TransformPropagate)
|
||||||
.before(VisibilitySystems::UpdatePerspectiveFrusta),
|
.before(VisibilitySystems::UpdatePerspectiveFrusta),
|
||||||
);
|
);
|
||||||
app.add_systems(Startup, setup_xr_cameras);
|
app.add_systems(XrSetup, setup_xr_cameras);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,6 +89,7 @@ fn setup_binding_recommendations(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn setup_xr_cameras(mut commands: Commands) {
|
fn setup_xr_cameras(mut commands: Commands) {
|
||||||
|
info!("WTF?!");
|
||||||
//this needs to do the whole xr tracking volume not just cameras
|
//this needs to do the whole xr tracking volume not just cameras
|
||||||
//get the root?
|
//get the root?
|
||||||
let tracking_root = commands
|
let tracking_root = commands
|
||||||
|
|||||||
Reference in New Issue
Block a user