feat: update to bevy 0.17 and use individual bevy crates
Signed-off-by: Schmarni <marnistromer@gmail.com>
This commit is contained in:
1650
Cargo.lock
generated
1650
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
29
Cargo.toml
29
Cargo.toml
@@ -10,21 +10,30 @@ resolver = "2"
|
|||||||
members = ["crates/*", "crates/bevy_openxr/examples/android"]
|
members = ["crates/*", "crates/bevy_openxr/examples/android"]
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
bevy = { version = "0.16.0", default-features = false, features = [
|
bevy = "0.17"
|
||||||
"bevy_render",
|
bevy_ecs = { version = "0.17.0", default-features = false }
|
||||||
"bevy_core_pipeline",
|
bevy_math = { version = "0.17.0", default-features = false }
|
||||||
"bevy_winit",
|
bevy_render = { version = "0.17.0", default-features = false }
|
||||||
"bevy_pbr",
|
bevy_core_pipeline = { version = "0.17.0", default-features = false }
|
||||||
"bevy_window",
|
bevy_window = { version = "0.17.0", default-features = false }
|
||||||
"x11",
|
bevy_winit = { version = "0.17.0", default-features = false }
|
||||||
] }
|
bevy_pbr = { version = "0.17.0", default-features = false }
|
||||||
|
bevy_app = { version = "0.17.0", default-features = false }
|
||||||
|
bevy_reflect = { version = "0.17.0", default-features = false }
|
||||||
|
bevy_log = { version = "0.17.0", default-features = false }
|
||||||
|
bevy_gizmos = { version = "0.17.0", default-features = false }
|
||||||
|
bevy_camera = { version = "0.17.0", default-features = false }
|
||||||
|
bevy_color = { version = "0.17.0", default-features = false }
|
||||||
|
bevy_transform = { version = "0.17.0", default-features = false }
|
||||||
|
bevy_derive = { version = "0.17.0", default-features = false }
|
||||||
|
bevy_platform = { version = "0.17.0", default-features = false }
|
||||||
bevy_mod_xr = { path = "crates/bevy_xr", version = "0.3.0" }
|
bevy_mod_xr = { path = "crates/bevy_xr", version = "0.3.0" }
|
||||||
bevy_mod_openxr = { path = "crates/bevy_openxr", version = "0.3.0" }
|
bevy_mod_openxr = { path = "crates/bevy_openxr", version = "0.3.0" }
|
||||||
bevy_xr_utils = { path = "crates/bevy_xr_utils", version = "0.3.0" }
|
bevy_xr_utils = { path = "crates/bevy_xr_utils", version = "0.3.0" }
|
||||||
openxr = "0.19.0"
|
openxr = "0.19.0"
|
||||||
thiserror = "2.0.3"
|
thiserror = "2.0.3"
|
||||||
wgpu = "24.0.1"
|
wgpu = "26"
|
||||||
wgpu-hal = "24.0.2"
|
wgpu-hal = "26"
|
||||||
|
|
||||||
# Enable a small amount of optimization in the dev profile.
|
# Enable a small amount of optimization in the dev profile.
|
||||||
[profile.dev]
|
[profile.dev]
|
||||||
|
|||||||
@@ -8,13 +8,15 @@ license.workspace = true
|
|||||||
keywords = ["gamedev", "bevy", "Xr", "Vr", "OpenXR"]
|
keywords = ["gamedev", "bevy", "Xr", "Vr", "OpenXR"]
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["vulkan", "d3d12", "passthrough"]
|
default = ["vulkan"]
|
||||||
vulkan = ["dep:ash", "dep:android_system_properties"]
|
vulkan = ["dep:ash", "dep:android_system_properties"]
|
||||||
d3d12 = ["wgpu/dx12", "wgpu-hal/dx12", "dep:winapi"]
|
d3d12 = ["wgpu/dx12", "wgpu-hal/dx12", "dep:winapi"]
|
||||||
passthrough = []
|
passthrough = []
|
||||||
|
reflect = ["dep:bevy_reflect"]
|
||||||
|
window_support = ["dep:bevy_winit"]
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
bevy = { workspace = true, default-features = true }
|
bevy.workspace = true
|
||||||
|
|
||||||
[target.'cfg(target_os = "android")'.dependencies]
|
[target.'cfg(target_os = "android")'.dependencies]
|
||||||
ndk-context = "0.1"
|
ndk-context = "0.1"
|
||||||
@@ -23,7 +25,18 @@ android_system_properties = { version = "0.1.5", optional = true }
|
|||||||
|
|
||||||
# bevy can't be placed behind target or proc macros won't work properly
|
# bevy can't be placed behind target or proc macros won't work properly
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bevy.workspace = true
|
bevy_ecs.workspace = true
|
||||||
|
bevy_math.workspace = true
|
||||||
|
bevy_render.workspace = true
|
||||||
|
bevy_app.workspace = true
|
||||||
|
bevy_reflect = { workspace = true, optional = true }
|
||||||
|
bevy_log.workspace = true
|
||||||
|
bevy_transform.workspace = true
|
||||||
|
bevy_camera.workspace = true
|
||||||
|
bevy_derive.workspace = true
|
||||||
|
bevy_platform.workspace = true
|
||||||
|
bevy_winit = { workspace = true, optional = true }
|
||||||
|
bevy_window = { workspace = true, optional = true }
|
||||||
|
|
||||||
# all other dependencies are placed under this since on wasm, this crate is completely empty
|
# all other dependencies are placed under this since on wasm, this crate is completely empty
|
||||||
[target.'cfg(not(target_family = "wasm"))'.dependencies]
|
[target.'cfg(not(target_family = "wasm"))'.dependencies]
|
||||||
|
|||||||
@@ -10,14 +10,14 @@ publish = false
|
|||||||
bevy_mod_openxr.workspace = true
|
bevy_mod_openxr.workspace = true
|
||||||
bevy_xr_utils.workspace = true
|
bevy_xr_utils.workspace = true
|
||||||
bevy_mod_xr.workspace = true
|
bevy_mod_xr.workspace = true
|
||||||
bevy = { workspace = true, default-features = false, features = [
|
# bevy = { workspace = true, default-features = false, features = [
|
||||||
# Bevy 0.15 made GameActivity the default which breaks Quest builds
|
# # Bevy 0.15 made GameActivity the default which breaks Quest builds
|
||||||
# To use NativeActivity instead of GameActivity all of the features have to be listed manually
|
# # To use NativeActivity instead of GameActivity all of the features have to be listed manually
|
||||||
"android-native-activity",
|
# "android-native-activity",
|
||||||
"bevy_window",
|
# "bevy_window",
|
||||||
"multi_threaded",
|
# "multi_threaded",
|
||||||
"tonemapping_luts",
|
# "tonemapping_luts",
|
||||||
] }
|
# ] }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
reqwest = { version = "0.12", features = ["blocking"] }
|
reqwest = { version = "0.12", features = ["blocking"] }
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy_mod_openxr::{
|
use bevy_mod_openxr::{
|
||||||
add_xr_plugins, features::overlay::OxrOverlaySessionEvent, init::OxrInitPlugin,
|
add_xr_plugins, features::overlay::OxrOverlaySessionMessage, init::OxrInitPlugin,
|
||||||
resources::OxrSessionConfig, types::OxrExtensions,
|
resources::OxrSessionConfig, types::OxrExtensions,
|
||||||
};
|
};
|
||||||
use openxr::EnvironmentBlendMode;
|
use openxr::EnvironmentBlendMode;
|
||||||
@@ -36,20 +36,20 @@ fn main() {
|
|||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_main_session_changes(mut events: EventReader<OxrOverlaySessionEvent>) {
|
fn print_main_session_changes(mut events: MessageReader<OxrOverlaySessionMessage>) {
|
||||||
for event in events.read() {
|
for event in events.read() {
|
||||||
let OxrOverlaySessionEvent::MainSessionVisibilityChanged { visible, flags: _ } = event;
|
let OxrOverlaySessionMessage::MainSessionVisibilityChanged { visible, flags: _ } = event;
|
||||||
info!("main session visible: {visible}");
|
info!("main session visible: {visible}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_input(
|
fn handle_input(
|
||||||
keys: Res<ButtonInput<KeyCode>>,
|
keys: Res<ButtonInput<KeyCode>>,
|
||||||
mut end: EventWriter<bevy_mod_xr::session::XrEndSessionEvent>,
|
mut end: MessageWriter<bevy_mod_xr::session::XrEndSessionMessage>,
|
||||||
mut destroy: EventWriter<bevy_mod_xr::session::XrDestroySessionEvent>,
|
mut destroy: MessageWriter<bevy_mod_xr::session::XrDestroySessionMessage>,
|
||||||
mut begin: EventWriter<bevy_mod_xr::session::XrBeginSessionEvent>,
|
mut begin: MessageWriter<bevy_mod_xr::session::XrBeginSessionMessage>,
|
||||||
mut create: EventWriter<bevy_mod_xr::session::XrCreateSessionEvent>,
|
mut create: MessageWriter<bevy_mod_xr::session::XrCreateSessionMessage>,
|
||||||
mut request_exit: EventWriter<bevy_mod_xr::session::XrRequestExitEvent>,
|
mut request_exit: MessageWriter<bevy_mod_xr::session::XrRequestExitMessage>,
|
||||||
) {
|
) {
|
||||||
if keys.just_pressed(KeyCode::KeyE) {
|
if keys.just_pressed(KeyCode::KeyE) {
|
||||||
info!("sending end");
|
info!("sending end");
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ fn main() -> AppExit {
|
|||||||
app.run()
|
app.run()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn attach_set(actions: Res<ControllerActions>, mut attach: EventWriter<OxrAttachActionSet>) {
|
fn attach_set(actions: Res<ControllerActions>, mut attach: MessageWriter<OxrAttachActionSet>) {
|
||||||
attach.write(OxrAttachActionSet(actions.set.clone()));
|
attach.write(OxrAttachActionSet(actions.set.clone()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ struct ControllerActions {
|
|||||||
left: openxr::Action<Posef>,
|
left: openxr::Action<Posef>,
|
||||||
right: openxr::Action<Posef>,
|
right: openxr::Action<Posef>,
|
||||||
}
|
}
|
||||||
fn sync_actions(actions: Res<ControllerActions>, mut sync: EventWriter<OxrSyncActionSet>) {
|
fn sync_actions(actions: Res<ControllerActions>, mut sync: MessageWriter<OxrSyncActionSet>) {
|
||||||
sync.write(OxrSyncActionSet(actions.set.clone()));
|
sync.write(OxrSyncActionSet(actions.set.clone()));
|
||||||
}
|
}
|
||||||
/// set up a simple 3D scene
|
/// set up a simple 3D scene
|
||||||
@@ -81,7 +81,7 @@ fn setup(
|
|||||||
}
|
}
|
||||||
fn suggest_action_bindings(
|
fn suggest_action_bindings(
|
||||||
actions: Res<ControllerActions>,
|
actions: Res<ControllerActions>,
|
||||||
mut bindings: EventWriter<OxrSuggestActionBinding>,
|
mut bindings: MessageWriter<OxrSuggestActionBinding>,
|
||||||
) {
|
) {
|
||||||
bindings.write(OxrSuggestActionBinding {
|
bindings.write(OxrSuggestActionBinding {
|
||||||
action: actions.left.as_raw(),
|
action: actions.left.as_raw(),
|
||||||
|
|||||||
@@ -16,11 +16,11 @@ fn main() -> AppExit {
|
|||||||
|
|
||||||
fn handle_input(
|
fn handle_input(
|
||||||
keys: Res<ButtonInput<KeyCode>>,
|
keys: Res<ButtonInput<KeyCode>>,
|
||||||
mut end: EventWriter<bevy_mod_xr::session::XrEndSessionEvent>,
|
mut end: MessageWriter<bevy_mod_xr::session::XrEndSessionMessage>,
|
||||||
mut destroy: EventWriter<bevy_mod_xr::session::XrDestroySessionEvent>,
|
mut destroy: MessageWriter<bevy_mod_xr::session::XrDestroySessionMessage>,
|
||||||
mut begin: EventWriter<bevy_mod_xr::session::XrBeginSessionEvent>,
|
mut begin: MessageWriter<bevy_mod_xr::session::XrBeginSessionMessage>,
|
||||||
mut create: EventWriter<bevy_mod_xr::session::XrCreateSessionEvent>,
|
mut create: MessageWriter<bevy_mod_xr::session::XrCreateSessionMessage>,
|
||||||
mut request_exit: EventWriter<bevy_mod_xr::session::XrRequestExitEvent>,
|
mut request_exit: MessageWriter<bevy_mod_xr::session::XrRequestExitMessage>,
|
||||||
state: Res<XrState>,
|
state: Res<XrState>,
|
||||||
) {
|
) {
|
||||||
if keys.just_pressed(KeyCode::KeyE) {
|
if keys.just_pressed(KeyCode::KeyE) {
|
||||||
|
|||||||
@@ -1,11 +1,15 @@
|
|||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
|
||||||
use bevy::ecs::schedule::ScheduleLabel;
|
use bevy_app::{App, Plugin, Update};
|
||||||
use bevy::ecs::system::RunSystemOnce;
|
use bevy_ecs::message::{Message, MessageReader};
|
||||||
use bevy::platform::collections::HashMap;
|
use bevy_ecs::schedule::common_conditions::on_message;
|
||||||
use bevy::prelude::*;
|
use bevy_ecs::schedule::{IntoScheduleConfigs as _, Schedule, ScheduleLabel};
|
||||||
use bevy_mod_xr::session::XrSessionCreatedEvent;
|
use bevy_ecs::system::{Res, RunSystemOnce};
|
||||||
|
use bevy_ecs::world::World;
|
||||||
|
use bevy_log::error;
|
||||||
|
use bevy_mod_xr::session::XrSessionCreatedMessage;
|
||||||
|
use bevy_platform::collections::HashMap;
|
||||||
use openxr::sys::ActionSuggestedBinding;
|
use openxr::sys::ActionSuggestedBinding;
|
||||||
|
|
||||||
use crate::resources::OxrInstance;
|
use crate::resources::OxrInstance;
|
||||||
@@ -13,10 +17,10 @@ use crate::resources::OxrInstance;
|
|||||||
impl Plugin for OxrActionBindingPlugin {
|
impl Plugin for OxrActionBindingPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.add_schedule(Schedule::new(OxrSendActionBindings));
|
app.add_schedule(Schedule::new(OxrSendActionBindings));
|
||||||
app.add_event::<OxrSuggestActionBinding>();
|
app.add_message::<OxrSuggestActionBinding>();
|
||||||
app.add_systems(
|
app.add_systems(
|
||||||
Update,
|
Update,
|
||||||
run_action_binding_sugestion.run_if(on_event::<XrSessionCreatedEvent>),
|
run_action_binding_sugestion.run_if(on_message::<XrSessionCreatedMessage>),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -28,7 +32,7 @@ pub(crate) fn run_action_binding_sugestion(world: &mut World) {
|
|||||||
_ = world.run_system_once(bind_actions);
|
_ = world.run_system_once(bind_actions);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bind_actions(instance: Res<OxrInstance>, mut actions: EventReader<OxrSuggestActionBinding>) {
|
fn bind_actions(instance: Res<OxrInstance>, mut actions: MessageReader<OxrSuggestActionBinding>) {
|
||||||
let mut bindings: HashMap<&str, Vec<ActionSuggestedBinding>> = HashMap::new();
|
let mut bindings: HashMap<&str, Vec<ActionSuggestedBinding>> = HashMap::new();
|
||||||
for e in actions.read() {
|
for e in actions.read() {
|
||||||
bindings.entry(&e.interaction_profile).or_default().extend(
|
bindings.entry(&e.interaction_profile).or_default().extend(
|
||||||
@@ -88,7 +92,7 @@ fn bind_actions(instance: Res<OxrInstance>, mut actions: EventReader<OxrSuggestA
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Event, Clone)]
|
#[derive(Message, Clone)]
|
||||||
/// Only Send this for Actions that were not attached yet!
|
/// Only Send this for Actions that were not attached yet!
|
||||||
pub struct OxrSuggestActionBinding {
|
pub struct OxrSuggestActionBinding {
|
||||||
pub action: openxr::sys::Action,
|
pub action: openxr::sys::Action,
|
||||||
@@ -97,6 +101,5 @@ pub struct OxrSuggestActionBinding {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct OxrActionBindingPlugin;
|
pub struct OxrActionBindingPlugin;
|
||||||
// Maybe use a SystemSet in an XrStartup Schedule?
|
|
||||||
#[derive(ScheduleLabel, Hash, Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(ScheduleLabel, Hash, Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub struct OxrSendActionBindings;
|
pub struct OxrSendActionBindings;
|
||||||
|
|||||||
@@ -1,20 +1,22 @@
|
|||||||
use crate::{action_binding::run_action_binding_sugestion, session::OxrSession};
|
use crate::{action_binding::run_action_binding_sugestion, session::OxrSession};
|
||||||
use bevy::prelude::*;
|
use bevy_app::{App, Plugin, PostUpdate};
|
||||||
use bevy_mod_xr::session::XrSessionCreatedEvent;
|
use bevy_ecs::{message::{Message, MessageReader}, schedule::{IntoScheduleConfigs as _, common_conditions::on_message}, system::Res};
|
||||||
|
use bevy_log::{error, info};
|
||||||
|
use bevy_mod_xr::session::XrSessionCreatedMessage;
|
||||||
|
|
||||||
impl Plugin for OxrActionAttachingPlugin {
|
impl Plugin for OxrActionAttachingPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.add_event::<OxrAttachActionSet>();
|
app.add_message::<OxrAttachActionSet>();
|
||||||
app.add_systems(
|
app.add_systems(
|
||||||
PostUpdate,
|
PostUpdate,
|
||||||
attach_sets
|
attach_sets
|
||||||
.run_if(on_event::<XrSessionCreatedEvent>)
|
.run_if(on_message::<XrSessionCreatedMessage>)
|
||||||
.after(run_action_binding_sugestion),
|
.after(run_action_binding_sugestion),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn attach_sets(session: Res<OxrSession>, mut events: EventReader<OxrAttachActionSet>) {
|
fn attach_sets(session: Res<OxrSession>, mut events: MessageReader<OxrAttachActionSet>) {
|
||||||
let sets = events.read().map(|v| &v.0).collect::<Vec<_>>();
|
let sets = events.read().map(|v| &v.0).collect::<Vec<_>>();
|
||||||
if sets.is_empty() {
|
if sets.is_empty() {
|
||||||
return;
|
return;
|
||||||
@@ -36,7 +38,7 @@ fn attach_sets(session: Res<OxrSession>, mut events: EventReader<OxrAttachAction
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Event, Clone)]
|
#[derive(Message, Clone)]
|
||||||
/// Send this event for every ActionSet you want to attach to the [`OxrSession`] once the Session Status changed to Ready. all requests will
|
/// Send this event for every ActionSet you want to attach to the [`OxrSession`] once the Session Status changed to Ready. all requests will
|
||||||
/// be applied in [`PostUpdate`]
|
/// be applied in [`PostUpdate`]
|
||||||
pub struct OxrAttachActionSet(pub openxr::ActionSet);
|
pub struct OxrAttachActionSet(pub openxr::ActionSet);
|
||||||
|
|||||||
@@ -1,12 +1,15 @@
|
|||||||
|
use bevy_app::{App, Plugin, PreUpdate};
|
||||||
|
use bevy_ecs::{message::{Message, MessageReader}, schedule::{IntoScheduleConfigs as _, SystemSet}, system::Res};
|
||||||
|
use bevy_log::warn;
|
||||||
|
|
||||||
use crate::{openxr_session_running, session::OxrSession};
|
use crate::{openxr_session_running, session::OxrSession};
|
||||||
use bevy::prelude::*;
|
|
||||||
|
|
||||||
#[derive(SystemSet, Debug, Hash, PartialEq, Eq, Clone, Copy)]
|
#[derive(SystemSet, Debug, Hash, PartialEq, Eq, Clone, Copy)]
|
||||||
pub struct OxrActionSetSyncSet;
|
pub struct OxrActionSetSyncSet;
|
||||||
|
|
||||||
impl Plugin for OxrActionSyncingPlugin {
|
impl Plugin for OxrActionSyncingPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.add_event::<OxrSyncActionSet>();
|
app.add_message::<OxrSyncActionSet>();
|
||||||
app.add_systems(
|
app.add_systems(
|
||||||
PreUpdate,
|
PreUpdate,
|
||||||
sync_sets
|
sync_sets
|
||||||
@@ -16,8 +19,8 @@ impl Plugin for OxrActionSyncingPlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sync_sets(session: Res<OxrSession>, mut events: EventReader<OxrSyncActionSet>) {
|
fn sync_sets(session: Res<OxrSession>, mut messages: MessageReader<OxrSyncActionSet>) {
|
||||||
let sets = events
|
let sets = messages
|
||||||
.read()
|
.read()
|
||||||
.map(|v| &v.0)
|
.map(|v| &v.0)
|
||||||
.map(openxr::ActiveActionSet::new)
|
.map(openxr::ActiveActionSet::new)
|
||||||
@@ -31,7 +34,7 @@ fn sync_sets(session: Res<OxrSession>, mut events: EventReader<OxrSyncActionSet>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Event, Clone)]
|
#[derive(Message, Clone)]
|
||||||
/// Send this event for every ActionSet you want to attach to the [`OxrSession`] once the Session Status changed to Ready. all requests will
|
/// Send this event for every ActionSet you want to attach to the [`OxrSession`] once the Session Status changed to Ready. all requests will
|
||||||
pub struct OxrSyncActionSet(pub openxr::ActionSet);
|
pub struct OxrSyncActionSet(pub openxr::ActionSet);
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use bevy::{ecs::resource::Resource, render::extract_resource::ExtractResource};
|
use bevy_ecs::resource::Resource;
|
||||||
|
use bevy_render::extract_resource::ExtractResource;
|
||||||
use openxr::EnvironmentBlendMode;
|
use openxr::EnvironmentBlendMode;
|
||||||
|
|
||||||
#[derive(Resource, ExtractResource, Clone)]
|
#[derive(Resource, ExtractResource, Clone)]
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use bevy::prelude::{Deref, DerefMut, Resource};
|
use bevy_derive::{Deref, DerefMut};
|
||||||
|
use bevy_ecs::resource::Resource;
|
||||||
use openxr::ExtensionSet;
|
use openxr::ExtensionSet;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, Deref, DerefMut, Resource)]
|
#[derive(Clone, Debug, Eq, PartialEq, Deref, DerefMut, Resource)]
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
use bevy::prelude::*;
|
use bevy_log::error;
|
||||||
use bevy::render::Render;
|
use bevy_log::info;
|
||||||
use bevy::render::RenderApp;
|
use bevy_render::Render;
|
||||||
use bevy::render::RenderSet;
|
use bevy_render::RenderApp;
|
||||||
|
use bevy_render::RenderSystems;
|
||||||
use openxr::sys::SystemPassthroughProperties2FB;
|
use openxr::sys::SystemPassthroughProperties2FB;
|
||||||
use openxr::PassthroughCapabilityFlagsFB;
|
use openxr::PassthroughCapabilityFlagsFB;
|
||||||
|
|
||||||
@@ -105,7 +106,7 @@ pub fn supports_passthrough(instance: &OxrInstance, system: OxrSystemId) -> OxrR
|
|||||||
system.0,
|
system.0,
|
||||||
p.as_mut_ptr(),
|
p.as_mut_ptr(),
|
||||||
))?;
|
))?;
|
||||||
bevy::log::info!(
|
info!(
|
||||||
"From supports_passthrough: Passthrough capabilities: {:?}",
|
"From supports_passthrough: Passthrough capabilities: {:?}",
|
||||||
properties.capabilities
|
properties.capabilities
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,4 +1,12 @@
|
|||||||
use bevy::prelude::*;
|
use bevy_app::{App, Plugin, PreUpdate, Startup};
|
||||||
|
use bevy_derive::{Deref, DerefMut};
|
||||||
|
use bevy_ecs::component::Component;
|
||||||
|
use bevy_ecs::entity::Entity;
|
||||||
|
use bevy_ecs::query::{Or, With};
|
||||||
|
use bevy_ecs::schedule::IntoScheduleConfigs as _;
|
||||||
|
use bevy_ecs::system::{Commands, Query, Res};
|
||||||
|
use bevy_ecs::world::World;
|
||||||
|
use bevy_log::{debug, error, warn};
|
||||||
use bevy_mod_xr::hands::{
|
use bevy_mod_xr::hands::{
|
||||||
spawn_hand_bones, HandBone, HandSide, SpawnHandTracker, SpawnHandTrackerCommandExecutor,
|
spawn_hand_bones, HandBone, HandSide, SpawnHandTracker, SpawnHandTrackerCommandExecutor,
|
||||||
XrHandBoneRadius,
|
XrHandBoneRadius,
|
||||||
@@ -9,6 +17,7 @@ use bevy_mod_xr::spaces::{
|
|||||||
XrPrimaryReferenceSpace, XrReferenceSpace, XrSpaceLocationFlags, XrSpaceSyncSet,
|
XrPrimaryReferenceSpace, XrReferenceSpace, XrSpaceLocationFlags, XrSpaceSyncSet,
|
||||||
XrSpaceVelocityFlags, XrVelocity,
|
XrSpaceVelocityFlags, XrVelocity,
|
||||||
};
|
};
|
||||||
|
use bevy_transform::components::Transform;
|
||||||
use openxr::{SpaceLocationFlags, SpaceVelocityFlags};
|
use openxr::{SpaceLocationFlags, SpaceVelocityFlags};
|
||||||
|
|
||||||
use crate::helper_traits::ToVec3;
|
use crate::helper_traits::ToVec3;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
use std::{mem, ptr};
|
use std::{mem, ptr};
|
||||||
|
|
||||||
use bevy::prelude::*;
|
use bevy_app::{App, First, Plugin};
|
||||||
|
use bevy_ecs::{message::{Message, MessageWriter}, resource::Resource, schedule::IntoScheduleConfigs as _, system::{NonSendMut, Res}};
|
||||||
use openxr::{sys, Event};
|
use openxr::{sys, Event};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@@ -14,8 +15,8 @@ use crate::{
|
|||||||
pub struct OxrOverlayPlugin;
|
pub struct OxrOverlayPlugin;
|
||||||
|
|
||||||
impl Plugin for OxrOverlayPlugin {
|
impl Plugin for OxrOverlayPlugin {
|
||||||
fn build(&self, app: &mut bevy::prelude::App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.add_event::<OxrOverlaySessionEvent>();
|
app.add_message::<OxrOverlaySessionMessage>();
|
||||||
app.init_resource::<OxrOverlaySettings>();
|
app.init_resource::<OxrOverlaySettings>();
|
||||||
app.add_systems(
|
app.add_systems(
|
||||||
First,
|
First,
|
||||||
@@ -25,9 +26,9 @@ impl Plugin for OxrOverlayPlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_overlay_event(event: OxrEventIn, mut writer: EventWriter<OxrOverlaySessionEvent>) {
|
fn handle_overlay_event(event: OxrEventIn, mut writer: MessageWriter<OxrOverlaySessionMessage>) {
|
||||||
if let Event::MainSessionVisibilityChangedEXTX(event) = *event {
|
if let Event::MainSessionVisibilityChangedEXTX(event) = *event {
|
||||||
writer.write(OxrOverlaySessionEvent::MainSessionVisibilityChanged {
|
writer.write(OxrOverlaySessionMessage::MainSessionVisibilityChanged {
|
||||||
visible: event.visible(),
|
visible: event.visible(),
|
||||||
flags: event.flags(),
|
flags: event.flags(),
|
||||||
});
|
});
|
||||||
@@ -62,8 +63,8 @@ fn add_overlay_info_to_chain(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Event, Clone, Copy, Debug)]
|
#[derive(Message, Clone, Copy, Debug)]
|
||||||
pub enum OxrOverlaySessionEvent {
|
pub enum OxrOverlaySessionMessage {
|
||||||
MainSessionVisibilityChanged {
|
MainSessionVisibilityChanged {
|
||||||
visible: bool,
|
visible: bool,
|
||||||
flags: openxr::OverlayMainSessionFlagsEXTX,
|
flags: openxr::OverlayMainSessionFlagsEXTX,
|
||||||
|
|||||||
@@ -5,7 +5,8 @@ pub mod vulkan;
|
|||||||
|
|
||||||
use std::{any::TypeId, ffi::CStr};
|
use std::{any::TypeId, ffi::CStr};
|
||||||
|
|
||||||
use bevy::{ecs::resource::Resource, math::UVec2};
|
use bevy_ecs::resource::Resource;
|
||||||
|
use bevy_math::UVec2;
|
||||||
use openxr::{FrameStream, FrameWaiter, Session};
|
use openxr::{FrameStream, FrameWaiter, Session};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
|||||||
@@ -2,10 +2,11 @@ use std::ffi::{c_void, CStr, CString};
|
|||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use ash::vk::{self, Handle};
|
use ash::vk::{self, Handle};
|
||||||
use bevy::log::{debug, error};
|
use bevy_log::{debug, error};
|
||||||
use bevy::math::UVec2;
|
use bevy_math::UVec2;
|
||||||
use openxr::{sys, Version};
|
use openxr::{sys, Version};
|
||||||
use wgpu::InstanceFlags;
|
use wgpu::{InstanceFlags, MemoryBudgetThresholds};
|
||||||
|
use wgpu::TextureUses;
|
||||||
use wgpu_hal::api::Vulkan;
|
use wgpu_hal::api::Vulkan;
|
||||||
use wgpu_hal::Api;
|
use wgpu_hal::Api;
|
||||||
|
|
||||||
@@ -53,7 +54,15 @@ unsafe impl GraphicsExt for openxr::Vulkan {
|
|||||||
) -> Result<wgpu::Texture> {
|
) -> Result<wgpu::Texture> {
|
||||||
let color_image = vk::Image::from_raw(color_image);
|
let color_image = vk::Image::from_raw(color_image);
|
||||||
let wgpu_hal_texture = unsafe {
|
let wgpu_hal_texture = unsafe {
|
||||||
<wgpu_hal::vulkan::Api as wgpu_hal::Api>::Device::texture_from_raw(
|
let hal_dev =
|
||||||
|
device
|
||||||
|
.as_hal::<wgpu_hal::vulkan::Api>()
|
||||||
|
.ok_or(OxrError::GraphicsBackendMismatch {
|
||||||
|
item: "Wgpu Device",
|
||||||
|
backend: "unknown",
|
||||||
|
expected_backend: "vulkan",
|
||||||
|
})?;
|
||||||
|
hal_dev.texture_from_raw(
|
||||||
color_image,
|
color_image,
|
||||||
&wgpu_hal::TextureDescriptor {
|
&wgpu_hal::TextureDescriptor {
|
||||||
label: Some("VR Swapchain"),
|
label: Some("VR Swapchain"),
|
||||||
@@ -66,7 +75,7 @@ unsafe impl GraphicsExt for openxr::Vulkan {
|
|||||||
sample_count: 1,
|
sample_count: 1,
|
||||||
dimension: wgpu::TextureDimension::D2,
|
dimension: wgpu::TextureDimension::D2,
|
||||||
format,
|
format,
|
||||||
usage: wgpu_hal::TextureUses::COLOR_TARGET | wgpu_hal::TextureUses::COPY_DST,
|
usage: TextureUses::COLOR_TARGET | TextureUses::COPY_DST,
|
||||||
memory_flags: wgpu_hal::MemoryFlags::empty(),
|
memory_flags: wgpu_hal::MemoryFlags::empty(),
|
||||||
view_formats: vec![],
|
view_formats: vec![],
|
||||||
},
|
},
|
||||||
@@ -151,7 +160,7 @@ unsafe impl GraphicsExt for openxr::Vulkan {
|
|||||||
vk_physical_device,
|
vk_physical_device,
|
||||||
instance_exts,
|
instance_exts,
|
||||||
flags,
|
flags,
|
||||||
device_exts.into(),
|
device_exts,
|
||||||
|info| unsafe {
|
|info| unsafe {
|
||||||
let vk_device = instance
|
let vk_device = instance
|
||||||
.create_vulkan_device(
|
.create_vulkan_device(
|
||||||
@@ -262,8 +271,8 @@ unsafe impl GraphicsExt for openxr::Vulkan {
|
|||||||
vk_physical_device,
|
vk_physical_device,
|
||||||
instance_exts,
|
instance_exts,
|
||||||
instance_flags,
|
instance_flags,
|
||||||
device_exts.into(),
|
device_exts,
|
||||||
|info| unsafe { Ok(vk_instance.create_device(vk_physical_device, &info, None)?) },
|
|info| unsafe { Ok(vk_instance.create_device(vk_physical_device, info, None)?) },
|
||||||
)
|
)
|
||||||
.map(|v| v.0)
|
.map(|v| v.0)
|
||||||
}
|
}
|
||||||
@@ -275,7 +284,7 @@ fn get_extensions(
|
|||||||
) -> Result<(wgpu::InstanceFlags, Vec<&'static CStr>, Vec<&'static CStr>)> {
|
) -> Result<(wgpu::InstanceFlags, Vec<&'static CStr>, Vec<&'static CStr>)> {
|
||||||
let flags = wgpu::InstanceFlags::default().with_env();
|
let flags = wgpu::InstanceFlags::default().with_env();
|
||||||
let mut instance_exts =
|
let mut instance_exts =
|
||||||
<Vulkan as Api>::Instance::desired_extensions(&vk_entry, VK_TARGET_VERSION_ASH, flags)?;
|
<Vulkan as Api>::Instance::desired_extensions(vk_entry, VK_TARGET_VERSION_ASH, flags)?;
|
||||||
let mut device_exts = vec![
|
let mut device_exts = vec![
|
||||||
ash::khr::swapchain::NAME,
|
ash::khr::swapchain::NAME,
|
||||||
ash::khr::draw_indirect_count::NAME,
|
ash::khr::draw_indirect_count::NAME,
|
||||||
@@ -370,6 +379,7 @@ fn init_from_instance_and_dev(
|
|||||||
None,
|
None,
|
||||||
instance_exts,
|
instance_exts,
|
||||||
instance_flags,
|
instance_flags,
|
||||||
|
MemoryBudgetThresholds::default(),
|
||||||
has_nv_optimus,
|
has_nv_optimus,
|
||||||
None,
|
None,
|
||||||
)?
|
)?
|
||||||
@@ -442,8 +452,8 @@ fn init_from_instance_and_dev(
|
|||||||
required_features: wgpu_features,
|
required_features: wgpu_features,
|
||||||
required_limits: limits,
|
required_limits: limits,
|
||||||
memory_hints: wgpu::MemoryHints::Performance,
|
memory_hints: wgpu::MemoryHints::Performance,
|
||||||
|
trace: wgpu::Trace::Off,
|
||||||
},
|
},
|
||||||
None,
|
|
||||||
)
|
)
|
||||||
}?;
|
}?;
|
||||||
Ok((
|
Ok((
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use bevy::{math::Vec3A, prelude::*};
|
use bevy_math::{Isometry3d, Quat, Vec2, Vec3, Vec3A};
|
||||||
|
use bevy_transform::components::Transform;
|
||||||
|
|
||||||
pub trait ToPosef {
|
pub trait ToPosef {
|
||||||
fn to_posef(&self) -> openxr::Posef;
|
fn to_posef(&self) -> openxr::Posef;
|
||||||
|
|||||||
@@ -1,23 +1,45 @@
|
|||||||
use std::sync::atomic::Ordering;
|
use std::sync::atomic::Ordering;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use bevy::prelude::*;
|
use bevy_app::App;
|
||||||
use bevy::render::extract_resource::ExtractResourcePlugin;
|
use bevy_app::Plugin;
|
||||||
use bevy::render::renderer::RenderAdapter;
|
use bevy_ecs::message::MessageWriter;
|
||||||
use bevy::render::renderer::RenderAdapterInfo;
|
use bevy_ecs::message::Messages;
|
||||||
use bevy::render::renderer::RenderDevice;
|
use bevy_ecs::resource::Resource;
|
||||||
use bevy::render::renderer::RenderInstance;
|
use bevy_ecs::schedule::SystemCondition as _;
|
||||||
use bevy::render::renderer::RenderQueue;
|
use bevy_ecs::schedule::common_conditions::on_message;
|
||||||
use bevy::render::renderer::WgpuWrapper;
|
use bevy_ecs::schedule::common_conditions::resource_exists;
|
||||||
use bevy::render::settings::RenderCreation;
|
use bevy_ecs::schedule::IntoScheduleConfigs as _;
|
||||||
use bevy::render::MainWorld;
|
use bevy_ecs::system::Commands;
|
||||||
use bevy::render::Render;
|
use bevy_ecs::system::Local;
|
||||||
use bevy::render::RenderApp;
|
use bevy_ecs::system::Res;
|
||||||
use bevy::render::RenderDebugFlags;
|
use bevy_ecs::system::ResMut;
|
||||||
use bevy::render::RenderPlugin;
|
use bevy_ecs::world::World;
|
||||||
use bevy::winit::UpdateMode;
|
use bevy_log::debug;
|
||||||
use bevy::winit::WinitSettings;
|
use bevy_log::debug_span;
|
||||||
|
use bevy_log::error;
|
||||||
|
use bevy_log::info;
|
||||||
|
use bevy_log::warn;
|
||||||
|
use bevy_math::UVec2;
|
||||||
use bevy_mod_xr::session::*;
|
use bevy_mod_xr::session::*;
|
||||||
|
use bevy_render::extract_resource::ExtractResourcePlugin;
|
||||||
|
use bevy_render::renderer::RenderAdapter;
|
||||||
|
use bevy_render::renderer::RenderAdapterInfo;
|
||||||
|
use bevy_render::renderer::RenderDevice;
|
||||||
|
use bevy_render::renderer::RenderInstance;
|
||||||
|
use bevy_render::renderer::RenderQueue;
|
||||||
|
use bevy_render::renderer::WgpuWrapper;
|
||||||
|
use bevy_render::settings::RenderCreation;
|
||||||
|
use bevy_render::ExtractSchedule;
|
||||||
|
use bevy_render::MainWorld;
|
||||||
|
use bevy_render::Render;
|
||||||
|
use bevy_render::RenderApp;
|
||||||
|
use bevy_render::RenderDebugFlags;
|
||||||
|
use bevy_render::RenderPlugin;
|
||||||
|
#[cfg(feature = "window_support")]
|
||||||
|
use bevy_winit::UpdateMode;
|
||||||
|
#[cfg(feature = "window_support")]
|
||||||
|
use bevy_winit::WinitSettings;
|
||||||
|
|
||||||
use crate::error::OxrError;
|
use crate::error::OxrError;
|
||||||
use crate::graphics::*;
|
use crate::graphics::*;
|
||||||
@@ -63,15 +85,15 @@ pub struct OxrInitPlugin {
|
|||||||
impl Default for OxrInitPlugin {
|
impl Default for OxrInitPlugin {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
app_info: default(),
|
app_info: Default::default(),
|
||||||
exts: {
|
exts: {
|
||||||
let mut exts = OxrExtensions::default();
|
let mut exts = OxrExtensions::default();
|
||||||
exts.enable_hand_tracking();
|
exts.enable_hand_tracking();
|
||||||
exts
|
exts
|
||||||
},
|
},
|
||||||
backends: default(),
|
backends: Default::default(),
|
||||||
synchronous_pipeline_compilation: false,
|
synchronous_pipeline_compilation: false,
|
||||||
render_debug_flags: default(),
|
render_debug_flags: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -110,7 +132,7 @@ impl Plugin for OxrInitPlugin {
|
|||||||
(
|
(
|
||||||
create_xr_session
|
create_xr_session
|
||||||
.run_if(state_equals(XrState::Available))
|
.run_if(state_equals(XrState::Available))
|
||||||
.run_if(on_event::<XrCreateSessionEvent>),
|
.run_if(on_message::<XrCreateSessionMessage>),
|
||||||
(
|
(
|
||||||
destroy_xr_session,
|
destroy_xr_session,
|
||||||
(|v: Res<XrDestroySessionRender>| {
|
(|v: Res<XrDestroySessionRender>| {
|
||||||
@@ -120,16 +142,16 @@ impl Plugin for OxrInitPlugin {
|
|||||||
)
|
)
|
||||||
.chain()
|
.chain()
|
||||||
.run_if(state_matches!(XrState::Exiting { .. }))
|
.run_if(state_matches!(XrState::Exiting { .. }))
|
||||||
.run_if(on_event::<XrDestroySessionEvent>),
|
.run_if(on_message::<XrDestroySessionMessage>),
|
||||||
begin_xr_session
|
begin_xr_session
|
||||||
.run_if(state_equals(XrState::Ready))
|
.run_if(state_equals(XrState::Ready))
|
||||||
.run_if(on_event::<XrBeginSessionEvent>),
|
.run_if(on_message::<XrBeginSessionMessage>),
|
||||||
end_xr_session
|
end_xr_session
|
||||||
.run_if(state_equals(XrState::Stopping))
|
.run_if(state_equals(XrState::Stopping))
|
||||||
.run_if(on_event::<XrEndSessionEvent>),
|
.run_if(on_message::<XrEndSessionMessage>),
|
||||||
request_exit_xr_session
|
request_exit_xr_session
|
||||||
.run_if(session_created)
|
.run_if(session_created)
|
||||||
.run_if(on_event::<XrRequestExitEvent>),
|
.run_if(on_message::<XrRequestExitMessage>),
|
||||||
detect_session_destroyed,
|
detect_session_destroyed,
|
||||||
)
|
)
|
||||||
.in_set(XrHandleEvents::SessionStateUpdateEvents),
|
.in_set(XrHandleEvents::SessionStateUpdateEvents),
|
||||||
@@ -137,17 +159,20 @@ impl Plugin for OxrInitPlugin {
|
|||||||
.insert_resource(instance.clone())
|
.insert_resource(instance.clone())
|
||||||
.insert_resource(system_id)
|
.insert_resource(system_id)
|
||||||
.insert_resource(XrState::Available)
|
.insert_resource(XrState::Available)
|
||||||
.insert_resource(WinitSettings {
|
|
||||||
focused_mode: UpdateMode::Continuous,
|
|
||||||
unfocused_mode: UpdateMode::Continuous,
|
|
||||||
})
|
|
||||||
.insert_resource(OxrSessionStarted(false))
|
.insert_resource(OxrSessionStarted(false))
|
||||||
.insert_non_send_resource(graphics_info)
|
.insert_non_send_resource(graphics_info)
|
||||||
.init_non_send_resource::<OxrSessionCreateNextChain>();
|
.init_non_send_resource::<OxrSessionCreateNextChain>();
|
||||||
|
#[cfg(feature = "window_support")]
|
||||||
|
{
|
||||||
|
app.insert_resource(WinitSettings {
|
||||||
|
focused_mode: UpdateMode::Continuous,
|
||||||
|
unfocused_mode: UpdateMode::Continuous,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
app.world_mut()
|
app.world_mut()
|
||||||
.resource_mut::<Events<XrStateChanged>>()
|
.resource_mut::<Messages<XrStateChanged>>()
|
||||||
.send(XrStateChanged(XrState::Available));
|
.write(XrStateChanged(XrState::Available));
|
||||||
|
|
||||||
let render_app = app.sub_app_mut(RenderApp);
|
let render_app = app.sub_app_mut(RenderApp);
|
||||||
|
|
||||||
@@ -213,7 +238,7 @@ impl Plugin for OxrInitPlugin {
|
|||||||
fn detect_session_destroyed(
|
fn detect_session_destroyed(
|
||||||
mut last_state: Local<bool>,
|
mut last_state: Local<bool>,
|
||||||
state: Res<XrDestroySessionRender>,
|
state: Res<XrDestroySessionRender>,
|
||||||
mut sender: EventWriter<XrSessionDestroyedEvent>,
|
mut sender: MessageWriter<XrSessionDestroyedMessage>,
|
||||||
mut cmds: Commands,
|
mut cmds: Commands,
|
||||||
) {
|
) {
|
||||||
let state = state.0.load(Ordering::Relaxed);
|
let state = state.0.load(Ordering::Relaxed);
|
||||||
@@ -307,7 +332,7 @@ impl OxrInitPlugin {
|
|||||||
pub fn handle_events(
|
pub fn handle_events(
|
||||||
event: OxrEventIn,
|
event: OxrEventIn,
|
||||||
mut status: ResMut<XrState>,
|
mut status: ResMut<XrState>,
|
||||||
mut changed_event: EventWriter<XrStateChanged>,
|
mut changed_event: MessageWriter<XrStateChanged>,
|
||||||
) {
|
) {
|
||||||
use openxr::Event::*;
|
use openxr::Event::*;
|
||||||
match *event {
|
match *event {
|
||||||
@@ -511,7 +536,7 @@ pub fn create_xr_session(world: &mut World) {
|
|||||||
}
|
}
|
||||||
world.insert_non_send_resource(chain);
|
world.insert_non_send_resource(chain);
|
||||||
world.run_schedule(XrSessionCreated);
|
world.run_schedule(XrSessionCreated);
|
||||||
world.send_event(XrSessionCreatedEvent);
|
world.write_message(XrSessionCreatedMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn destroy_xr_session(world: &mut World) {
|
pub fn destroy_xr_session(world: &mut World) {
|
||||||
@@ -525,9 +550,7 @@ pub fn destroy_xr_session(world: &mut World) {
|
|||||||
world.insert_resource(XrState::Available);
|
world.insert_resource(XrState::Available);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn begin_xr_session(
|
pub fn begin_xr_session(world: &mut World) {
|
||||||
world: &mut World,
|
|
||||||
) {
|
|
||||||
let _span = debug_span!("xr_begin_session").entered();
|
let _span = debug_span!("xr_begin_session").entered();
|
||||||
world
|
world
|
||||||
.get_resource::<OxrSession>()
|
.get_resource::<OxrSession>()
|
||||||
@@ -539,9 +562,7 @@ pub fn begin_xr_session(
|
|||||||
world.run_schedule(XrPostSessionBegin);
|
world.run_schedule(XrPostSessionBegin);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn end_xr_session(
|
pub fn end_xr_session(world: &mut World) {
|
||||||
world: &mut World,
|
|
||||||
) {
|
|
||||||
world.run_schedule(XrPreSessionEnd);
|
world.run_schedule(XrPreSessionEnd);
|
||||||
let _span = debug_span!("xr_end_session").entered();
|
let _span = debug_span!("xr_end_session").entered();
|
||||||
world
|
world
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
use bevy::ecs::world::World;
|
use bevy_ecs::world::World;
|
||||||
use bevy_mod_xr::spaces::{XrPrimaryReferenceSpace, XrSpace};
|
use bevy_mod_xr::spaces::{XrPrimaryReferenceSpace, XrSpace};
|
||||||
use openxr::{sys, CompositionLayerFlags, Fovf, Posef, Rect2Di};
|
use openxr::{sys, CompositionLayerFlags, Fovf, Posef, Rect2Di};
|
||||||
|
|
||||||
@@ -63,7 +63,7 @@ impl LayerProvider for ProjectionLayer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl LayerProvider for PassthroughLayer {
|
impl LayerProvider for PassthroughLayer {
|
||||||
fn get(&self, world: &World) -> Option<Box<dyn CompositionLayer>> {
|
fn get(&self, world: &World) -> Option<Box<dyn CompositionLayer<'_>>> {
|
||||||
Some(Box::new(
|
Some(Box::new(
|
||||||
CompositionLayerPassthrough::new()
|
CompositionLayerPassthrough::new()
|
||||||
.layer_handle(world.get_resource::<OxrPassthroughLayer>()?)
|
.layer_handle(world.get_resource::<OxrPassthroughLayer>()?)
|
||||||
@@ -171,7 +171,7 @@ impl Default for CompositionLayerProjectionView<'_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// # Safety
|
/// # Safety
|
||||||
/// the header function must return a ref to a valid Composition Layer struct.
|
/// the header function must return a ref to a valid Composition Layer struct.
|
||||||
/// it has to use `repr(C)` and it has to follow the shape of a Composition Layer struct from the
|
/// it has to use `repr(C)` and it has to follow the shape of a Composition Layer struct from the
|
||||||
/// OpenXR specification
|
/// OpenXR specification
|
||||||
pub unsafe trait CompositionLayer<'a> {
|
pub unsafe trait CompositionLayer<'a> {
|
||||||
|
|||||||
@@ -1,13 +1,11 @@
|
|||||||
// use actions::XrActionPlugin;
|
// use actions::XrActionPlugin;
|
||||||
use bevy::{
|
use bevy_app::{PluginGroup, PluginGroupBuilder};
|
||||||
app::{PluginGroup, PluginGroupBuilder},
|
use bevy_ecs::system::Res;
|
||||||
prelude::Res,
|
|
||||||
render::RenderPlugin,
|
|
||||||
utils::default,
|
|
||||||
window::{PresentMode, Window, WindowPlugin},
|
|
||||||
};
|
|
||||||
use bevy_mod_xr::session::XrSessionPlugin;
|
use bevy_mod_xr::session::XrSessionPlugin;
|
||||||
use bevy_mod_xr::{camera::XrCameraPlugin, session::XrState};
|
use bevy_mod_xr::{camera::XrCameraPlugin, session::XrState};
|
||||||
|
use bevy_render::RenderPlugin;
|
||||||
|
#[cfg(feature = "window_support")]
|
||||||
|
use bevy_window::{PresentMode, Window, WindowPlugin};
|
||||||
use init::OxrInitPlugin;
|
use init::OxrInitPlugin;
|
||||||
use poll_events::OxrEventsPlugin;
|
use poll_events::OxrEventsPlugin;
|
||||||
use render::OxrRenderPlugin;
|
use render::OxrRenderPlugin;
|
||||||
@@ -54,7 +52,7 @@ pub fn openxr_session_running(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_xr_plugins<G: PluginGroup>(plugins: G) -> PluginGroupBuilder {
|
pub fn add_xr_plugins<G: PluginGroup>(plugins: G) -> PluginGroupBuilder {
|
||||||
plugins
|
let plugins = plugins
|
||||||
.build()
|
.build()
|
||||||
.disable::<RenderPlugin>()
|
.disable::<RenderPlugin>()
|
||||||
.add_before::<RenderPlugin>(XrSessionPlugin { auto_handle: true })
|
.add_before::<RenderPlugin>(XrSessionPlugin { auto_handle: true })
|
||||||
@@ -69,15 +67,17 @@ pub fn add_xr_plugins<G: PluginGroup>(plugins: G) -> PluginGroupBuilder {
|
|||||||
.add(action_set_syncing::OxrActionSyncingPlugin)
|
.add(action_set_syncing::OxrActionSyncingPlugin)
|
||||||
.add(features::overlay::OxrOverlayPlugin)
|
.add(features::overlay::OxrOverlayPlugin)
|
||||||
.add(spaces::OxrSpatialPlugin)
|
.add(spaces::OxrSpatialPlugin)
|
||||||
.add(spaces::OxrSpacePatchingPlugin)
|
.add(spaces::OxrSpacePatchingPlugin);
|
||||||
// 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
|
||||||
.set(WindowPlugin {
|
#[cfg(feature = "window_support")]
|
||||||
primary_window: Some(Window {
|
let plugins = plugins.set(WindowPlugin {
|
||||||
transparent: true,
|
primary_window: Some(Window {
|
||||||
present_mode: PresentMode::AutoNoVsync,
|
transparent: true,
|
||||||
..default()
|
present_mode: PresentMode::AutoNoVsync,
|
||||||
}),
|
|
||||||
..default()
|
..default()
|
||||||
})
|
}),
|
||||||
|
..default()
|
||||||
|
});
|
||||||
|
plugins
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
use super::{openxr_session_available, resources::OxrInstance};
|
use super::{openxr_session_available, resources::OxrInstance};
|
||||||
use bevy::{ecs::system::SystemId, prelude::*};
|
use bevy_app::{App, Plugin};
|
||||||
|
use bevy_derive::Deref;
|
||||||
|
use bevy_ecs::{entity::Entity, resource::Resource, schedule::IntoScheduleConfigs as _, system::{IntoSystem, SystemId, SystemInput}, world::World};
|
||||||
|
use bevy_log::{debug_span, error};
|
||||||
use bevy_mod_xr::session::{XrFirst, XrHandleEvents};
|
use bevy_mod_xr::session::{XrFirst, XrHandleEvents};
|
||||||
use openxr::{Event, EventDataBuffer};
|
use openxr::{Event, EventDataBuffer};
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,17 @@
|
|||||||
use bevy::{
|
use bevy_app::{App, Plugin};
|
||||||
prelude::*,
|
use bevy_ecs::{
|
||||||
render::{extract_resource::ExtractResourcePlugin, RenderApp},
|
entity::Entity,
|
||||||
|
query::With,
|
||||||
|
resource::Resource,
|
||||||
|
system::{Commands, Query, Res},
|
||||||
};
|
};
|
||||||
|
use bevy_log::error;
|
||||||
|
use bevy_math::Isometry3d;
|
||||||
use bevy_mod_xr::{
|
use bevy_mod_xr::{
|
||||||
session::{XrPreDestroySession, XrSessionCreated},
|
session::{XrPreDestroySession, XrSessionCreated},
|
||||||
spaces::{XrPrimaryReferenceSpace, XrReferenceSpace},
|
spaces::{XrPrimaryReferenceSpace, XrReferenceSpace},
|
||||||
};
|
};
|
||||||
|
use bevy_render::{RenderApp, extract_resource::ExtractResourcePlugin};
|
||||||
|
|
||||||
use crate::session::OxrSession;
|
use crate::session::OxrSession;
|
||||||
|
|
||||||
@@ -51,7 +57,7 @@ fn set_primary_ref_space(
|
|||||||
space_type: Res<OxrDefaultPrimaryReferenceSpaceType>,
|
space_type: Res<OxrDefaultPrimaryReferenceSpaceType>,
|
||||||
mut cmds: Commands,
|
mut cmds: Commands,
|
||||||
) {
|
) {
|
||||||
match session.create_reference_space(space_type.0, Transform::IDENTITY) {
|
match session.create_reference_space(space_type.0, Isometry3d::IDENTITY) {
|
||||||
Ok(space) => {
|
Ok(space) => {
|
||||||
cmds.insert_resource(XrPrimaryReferenceSpace(space));
|
cmds.insert_resource(XrPrimaryReferenceSpace(space));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,25 +1,33 @@
|
|||||||
use bevy::{
|
use bevy_app::{App, Plugin, PostUpdate};
|
||||||
prelude::*,
|
use bevy_camera::{Camera, ManualTextureViewHandle, Projection, RenderTarget};
|
||||||
render::{
|
use bevy_ecs::{
|
||||||
camera::{ManualTextureView, ManualTextureViewHandle, ManualTextureViews, RenderTarget},
|
change_detection::DetectChanges as _,
|
||||||
extract_resource::ExtractResourcePlugin,
|
entity::Entity,
|
||||||
pipelined_rendering::PipelinedRenderingPlugin,
|
schedule::{IntoScheduleConfigs as _, SystemSet},
|
||||||
view::{ExtractedView, NoFrustumCulling},
|
system::{Commands, Query, Res, ResMut},
|
||||||
Render, RenderApp,
|
world::World,
|
||||||
},
|
|
||||||
transform::TransformSystem,
|
|
||||||
};
|
};
|
||||||
|
use bevy_log::{debug_span, error, info};
|
||||||
|
use bevy_render::{
|
||||||
|
extract_resource::ExtractResourcePlugin,
|
||||||
|
pipelined_rendering::PipelinedRenderingPlugin,
|
||||||
|
texture::{ManualTextureView, ManualTextureViews},
|
||||||
|
view::ExtractedView,
|
||||||
|
Render, RenderApp,
|
||||||
|
};
|
||||||
|
|
||||||
use bevy_mod_xr::{
|
use bevy_mod_xr::{
|
||||||
camera::{calculate_projection, Fov, XrCamera, XrProjection, XrViewInit},
|
camera::{calculate_projection, Fov, XrCamera, XrProjection, XrViewInit},
|
||||||
session::{
|
session::{
|
||||||
XrFirst, XrHandleEvents, XrPreDestroySession, XrRenderSet, XrRootTransform,
|
XrFirst, XrHandleEvents, XrPreDestroySession, XrRenderSystems, XrRootTransform,
|
||||||
XrSessionCreated,
|
XrSessionCreated,
|
||||||
},
|
},
|
||||||
spaces::XrPrimaryReferenceSpace,
|
spaces::XrPrimaryReferenceSpace,
|
||||||
};
|
};
|
||||||
|
use bevy_transform::{components::Transform, TransformSystems};
|
||||||
use openxr::ViewStateFlags;
|
use openxr::ViewStateFlags;
|
||||||
|
|
||||||
use crate::{init::should_run_frame_loop, resources::*};
|
use crate::{helper_traits::ToTransform as _, init::should_run_frame_loop, resources::*};
|
||||||
use crate::{layer_builder::ProjectionLayer, session::OxrSession};
|
use crate::{layer_builder::ProjectionLayer, session::OxrSession};
|
||||||
|
|
||||||
use super::environment_blend_mode::OxrEnvironmentBlendModes;
|
use super::environment_blend_mode::OxrEnvironmentBlendModes;
|
||||||
@@ -88,9 +96,8 @@ impl Plugin for OxrRenderPlugin {
|
|||||||
.add_systems(
|
.add_systems(
|
||||||
PostUpdate,
|
PostUpdate,
|
||||||
(locate_views, update_views)
|
(locate_views, update_views)
|
||||||
.before(TransformSystem::TransformPropagate)
|
.before(TransformSystems::Propagate)
|
||||||
.chain()
|
.chain()
|
||||||
// .run_if(should_render)
|
|
||||||
.run_if(should_run_frame_loop),
|
.run_if(should_run_frame_loop),
|
||||||
)
|
)
|
||||||
.init_resource::<OxrViews>();
|
.init_resource::<OxrViews>();
|
||||||
@@ -109,7 +116,7 @@ impl Plugin for OxrRenderPlugin {
|
|||||||
wait_image,
|
wait_image,
|
||||||
)
|
)
|
||||||
.chain()
|
.chain()
|
||||||
.in_set(XrRenderSet::PreRender)
|
.in_set(XrRenderSystems::PreRender)
|
||||||
.run_if(should_run_frame_loop),
|
.run_if(should_run_frame_loop),
|
||||||
)
|
)
|
||||||
.add_systems(
|
.add_systems(
|
||||||
@@ -117,40 +124,12 @@ impl Plugin for OxrRenderPlugin {
|
|||||||
(release_image, end_frame)
|
(release_image, end_frame)
|
||||||
.chain()
|
.chain()
|
||||||
.run_if(should_run_frame_loop)
|
.run_if(should_run_frame_loop)
|
||||||
.in_set(XrRenderSet::PostRender),
|
.in_set(XrRenderSystems::PostRender),
|
||||||
)
|
)
|
||||||
.insert_resource(OxrRenderLayers(vec![Box::new(ProjectionLayer)]));
|
.insert_resource(OxrRenderLayers(vec![Box::new(ProjectionLayer)]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// fn update_rendering(app_world: &mut World, _sub_app: &mut App) {
|
|
||||||
// app_world.resource_scope(|world, main_thread_executor: Mut<MainThreadExecutor>| {
|
|
||||||
// world.resource_scope(|world, mut render_channels: Mut<RenderAppChannels>| {
|
|
||||||
// // we use a scope here to run any main thread tasks that the render world still needs to run
|
|
||||||
// // while we wait for the render world to be received.
|
|
||||||
// let mut render_app = ComputeTaskPool::get()
|
|
||||||
// .scope_with_executor(true, Some(&*main_thread_executor.0), |s| {
|
|
||||||
// s.spawn(async { render_channels.recv().await });
|
|
||||||
// })
|
|
||||||
// .pop()
|
|
||||||
// .unwrap();
|
|
||||||
|
|
||||||
// if matches!(world.resource::<XrState>(), XrState::Stopping) {
|
|
||||||
// world.run_schedule(XrEndSession);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if matches!(world.resource::<XrState>(), XrState::Exiting { .. }) {
|
|
||||||
// world.run_schedule(XrDestroySession);
|
|
||||||
// render_app.app.world.run_schedule(XrDestroySession);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// render_app.extract(world);
|
|
||||||
|
|
||||||
// render_channels.send_blocking(render_app);
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
pub const XR_TEXTURE_INDEX: u32 = 3383858418;
|
pub const XR_TEXTURE_INDEX: u32 = 3383858418;
|
||||||
|
|
||||||
pub fn clean_views(
|
pub fn clean_views(
|
||||||
@@ -185,7 +164,7 @@ pub fn init_views<const SPAWN_CAMERAS: bool>(
|
|||||||
},
|
},
|
||||||
XrCamera(index),
|
XrCamera(index),
|
||||||
Projection::custom(XrProjection::default()),
|
Projection::custom(XrProjection::default()),
|
||||||
NoFrustumCulling,
|
// NoFrustumCulling,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -283,12 +262,7 @@ pub fn update_views(
|
|||||||
);
|
);
|
||||||
projection.projection_matrix = projection_matrix;
|
projection.projection_matrix = projection_matrix;
|
||||||
|
|
||||||
let openxr::Quaternionf { x, y, z, w } = view.pose.orientation;
|
*transform = view.pose.to_transform();
|
||||||
let rotation = Quat::from_xyzw(x, y, z, w);
|
|
||||||
transform.rotation = rotation;
|
|
||||||
let openxr::Vector3f { x, y, z } = view.pose.position;
|
|
||||||
let translation = Vec3::new(x, y, z);
|
|
||||||
transform.translation = translation;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -301,14 +275,7 @@ pub fn update_views_render_world(
|
|||||||
let Some(view) = views.get(camera.0 as usize) else {
|
let Some(view) = views.get(camera.0 as usize) else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
let mut transform = Transform::IDENTITY;
|
extracted_view.world_from_view = root.0.mul_transform(view.pose.to_transform());
|
||||||
let openxr::Quaternionf { x, y, z, w } = view.pose.orientation;
|
|
||||||
let rotation = Quat::from_xyzw(x, y, z, w);
|
|
||||||
transform.rotation = rotation;
|
|
||||||
let openxr::Vector3f { x, y, z } = view.pose.position;
|
|
||||||
let translation = Vec3::new(x, y, z);
|
|
||||||
transform.translation = translation;
|
|
||||||
extracted_view.world_from_view = root.0.mul_transform(transform);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -345,7 +312,7 @@ pub fn add_texture_view(
|
|||||||
dimension: Some(wgpu::TextureViewDimension::D2),
|
dimension: Some(wgpu::TextureViewDimension::D2),
|
||||||
array_layer_count: Some(1),
|
array_layer_count: Some(1),
|
||||||
base_array_layer: index,
|
base_array_layer: index,
|
||||||
..default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
let view = ManualTextureView {
|
let view = ManualTextureView {
|
||||||
texture_view: view.into(),
|
texture_view: view.into(),
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
use bevy::prelude::*;
|
use bevy_derive::{Deref, DerefMut};
|
||||||
use bevy::render::extract_resource::ExtractResource;
|
use bevy_ecs::resource::Resource;
|
||||||
|
use bevy_math::UVec2;
|
||||||
|
use bevy_render::extract_resource::ExtractResource;
|
||||||
|
use bevy_log::error;
|
||||||
|
|
||||||
use crate::error::OxrError;
|
use crate::error::OxrError;
|
||||||
use crate::graphics::*;
|
use crate::graphics::*;
|
||||||
@@ -351,7 +354,7 @@ impl Default for OxrSessionConfig {
|
|||||||
Self {
|
Self {
|
||||||
blend_mode_preference: vec![openxr::EnvironmentBlendMode::OPAQUE],
|
blend_mode_preference: vec![openxr::EnvironmentBlendMode::OPAQUE],
|
||||||
formats: Some(vec![wgpu::TextureFormat::Rgba8UnormSrgb]),
|
formats: Some(vec![wgpu::TextureFormat::Rgba8UnormSrgb]),
|
||||||
resolutions: default(),
|
resolutions: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,8 @@ use std::ffi::c_void;
|
|||||||
use crate::next_chain::{OxrNextChain, OxrNextChainStructBase, OxrNextChainStructProvider};
|
use crate::next_chain::{OxrNextChain, OxrNextChainStructBase, OxrNextChainStructProvider};
|
||||||
use crate::resources::{OxrPassthrough, OxrPassthroughLayer, OxrSwapchain};
|
use crate::resources::{OxrPassthrough, OxrPassthroughLayer, OxrSwapchain};
|
||||||
use crate::types::{Result, SwapchainCreateInfo};
|
use crate::types::{Result, SwapchainCreateInfo};
|
||||||
use bevy::prelude::*;
|
use bevy_derive::Deref;
|
||||||
|
use bevy_ecs::resource::Resource;
|
||||||
use openxr::AnyGraphics;
|
use openxr::AnyGraphics;
|
||||||
|
|
||||||
use crate::graphics::{graphics_match, GraphicsExt, GraphicsType, GraphicsWrap};
|
use crate::graphics::{graphics_match, GraphicsExt, GraphicsType, GraphicsWrap};
|
||||||
|
|||||||
@@ -1,16 +1,24 @@
|
|||||||
use std::{mem::MaybeUninit, ptr, sync::Mutex};
|
use bevy_app::{App, Plugin, PreUpdate, Startup};
|
||||||
|
use bevy_ecs::{
|
||||||
use bevy::{platform::collections::hash_set::HashSet, prelude::*};
|
component::Component, message::MessageReader, schedule::IntoScheduleConfigs as _, system::{Query, Res, ResMut}
|
||||||
|
};
|
||||||
|
use bevy_log::{error, info};
|
||||||
|
use bevy_log::warn;
|
||||||
|
use bevy_math::Isometry3d;
|
||||||
use bevy_mod_xr::{
|
use bevy_mod_xr::{
|
||||||
session::{XrFirst, XrHandleEvents},
|
session::{XrFirst, XrHandleEvents},
|
||||||
spaces::{
|
spaces::{
|
||||||
XrDestroySpace, XrPrimaryReferenceSpace, XrReferenceSpace, XrSpace, XrSpaceLocationFlags, XrSpaceSyncSet, XrSpaceVelocityFlags, XrVelocity
|
XrDestroySpace, XrPrimaryReferenceSpace, XrReferenceSpace, XrSpace, XrSpaceLocationFlags,
|
||||||
|
XrSpaceSyncSet, XrSpaceVelocityFlags, XrVelocity,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
use bevy_platform::collections::hash_set::HashSet;
|
||||||
|
use bevy_transform::components::Transform;
|
||||||
use openxr::{
|
use openxr::{
|
||||||
sys, HandJointLocation, HandJointLocations, HandJointVelocities, HandJointVelocity,
|
sys, HandJointLocation, HandJointLocations, HandJointVelocities, HandJointVelocity,
|
||||||
ReferenceSpaceType, SpaceLocationFlags, SpaceVelocityFlags, HAND_JOINT_COUNT,
|
ReferenceSpaceType, SpaceLocationFlags, SpaceVelocityFlags, HAND_JOINT_COUNT,
|
||||||
};
|
};
|
||||||
|
use std::{mem::MaybeUninit, ptr, sync::Mutex};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
helper_traits::{ToPosef, ToQuat, ToVec3},
|
helper_traits::{ToPosef, ToQuat, ToVec3},
|
||||||
@@ -33,7 +41,7 @@ impl Plugin for OxrSpacePatchingPlugin {
|
|||||||
pub struct OxrSpatialPlugin;
|
pub struct OxrSpatialPlugin;
|
||||||
impl Plugin for OxrSpatialPlugin {
|
impl Plugin for OxrSpatialPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.add_event::<XrDestroySpace>()
|
app.add_message::<XrDestroySpace>()
|
||||||
.add_systems(
|
.add_systems(
|
||||||
XrFirst,
|
XrFirst,
|
||||||
destroy_space_event
|
destroy_space_event
|
||||||
@@ -51,7 +59,7 @@ impl Plugin for OxrSpatialPlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn destroy_space_event(instance: Res<OxrInstance>, mut events: EventReader<XrDestroySpace>) {
|
fn destroy_space_event(instance: Res<OxrInstance>, mut events: MessageReader<XrDestroySpace>) {
|
||||||
for space in events.read() {
|
for space in events.read() {
|
||||||
match instance.destroy_space(space.0) {
|
match instance.destroy_space(space.0) {
|
||||||
Ok(_) => (),
|
Ok(_) => (),
|
||||||
@@ -231,7 +239,7 @@ impl OxrSession {
|
|||||||
pub fn create_reference_space(
|
pub fn create_reference_space(
|
||||||
&self,
|
&self,
|
||||||
ref_space_type: ReferenceSpaceType,
|
ref_space_type: ReferenceSpaceType,
|
||||||
pose_in_ref_space: Transform,
|
pose_in_ref_space: Isometry3d,
|
||||||
) -> openxr::Result<XrReferenceSpace> {
|
) -> openxr::Result<XrReferenceSpace> {
|
||||||
let info = sys::ReferenceSpaceCreateInfo {
|
let info = sys::ReferenceSpaceCreateInfo {
|
||||||
ty: sys::ReferenceSpaceCreateInfo::TYPE,
|
ty: sys::ReferenceSpaceCreateInfo::TYPE,
|
||||||
@@ -579,6 +587,7 @@ fn cvt(x: sys::Result) -> openxr::Result<sys::Result> {
|
|||||||
Err(x)
|
Err(x)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[allow(clippy::obfuscated_if_else)]
|
||||||
unsafe fn create_view(flags: openxr::ViewStateFlags, raw: &MaybeUninit<sys::View>) -> openxr::View {
|
unsafe fn create_view(flags: openxr::ViewStateFlags, raw: &MaybeUninit<sys::View>) -> openxr::View {
|
||||||
// Applications *must* not read invalid parts of a poses, i.e. they may be uninitialized
|
// Applications *must* not read invalid parts of a poses, i.e. they may be uninitialized
|
||||||
let ptr = raw.as_ptr();
|
let ptr = raw.as_ptr();
|
||||||
@@ -596,6 +605,7 @@ unsafe fn create_view(flags: openxr::ViewStateFlags, raw: &MaybeUninit<sys::View
|
|||||||
fov: *ptr::addr_of!((*ptr).fov),
|
fov: *ptr::addr_of!((*ptr).fov),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[allow(clippy::obfuscated_if_else)]
|
||||||
unsafe fn create_space_location(raw: &MaybeUninit<sys::SpaceLocation>) -> openxr::SpaceLocation {
|
unsafe fn create_space_location(raw: &MaybeUninit<sys::SpaceLocation>) -> openxr::SpaceLocation {
|
||||||
// Applications *must* not read invalid parts of a pose, i.e. they may be uninitialized
|
// Applications *must* not read invalid parts of a pose, i.e. they may be uninitialized
|
||||||
let ptr = raw.as_ptr();
|
let ptr = raw.as_ptr();
|
||||||
@@ -614,6 +624,7 @@ unsafe fn create_space_location(raw: &MaybeUninit<sys::SpaceLocation>) -> openxr
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[allow(clippy::obfuscated_if_else)]
|
||||||
unsafe fn create_space_velocity(raw: &MaybeUninit<sys::SpaceVelocity>) -> openxr::SpaceVelocity {
|
unsafe fn create_space_velocity(raw: &MaybeUninit<sys::SpaceVelocity>) -> openxr::SpaceVelocity {
|
||||||
// Applications *must* not read invalid velocities, i.e. they may be uninitialized
|
// Applications *must* not read invalid velocities, i.e. they may be uninitialized
|
||||||
let ptr = raw.as_ptr();
|
let ptr = raw.as_ptr();
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ license.workspace = true
|
|||||||
|
|
||||||
# bevy can't be placed behind target or proc macros won't work properly
|
# bevy can't be placed behind target or proc macros won't work properly
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bevy.workspace = true
|
# bevy.workspace = true
|
||||||
|
|
||||||
# all dependencies are placed under this since on anything but wasm, this crate is completely empty
|
# all dependencies are placed under this since on anything but wasm, this crate is completely empty
|
||||||
[target.'cfg(target_family = "wasm")'.dependencies]
|
[target.'cfg(target_family = "wasm")'.dependencies]
|
||||||
|
|||||||
@@ -10,10 +10,21 @@ keywords = ["gamedev", "bevy", "Xr", "Vr"]
|
|||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
[features]
|
[features]
|
||||||
default = ["gizmos"]
|
default = ["gizmos"]
|
||||||
gizmos = ["bevy/bevy_gizmos"]
|
gizmos = ["dep:bevy_gizmos", "dep:bevy_color"]
|
||||||
|
reflect = ["dep:bevy_reflect"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bevy = { workspace = true, features = ["bevy_log"] }
|
bevy_ecs.workspace = true
|
||||||
|
bevy_math.workspace = true
|
||||||
|
bevy_render.workspace = true
|
||||||
|
bevy_app.workspace = true
|
||||||
|
bevy_reflect = { workspace = true, optional = true }
|
||||||
|
bevy_log.workspace = true
|
||||||
|
bevy_gizmos = { workspace = true, optional = true }
|
||||||
|
bevy_color = { workspace = true, optional = true }
|
||||||
|
bevy_transform.workspace = true
|
||||||
|
bevy_camera.workspace = true
|
||||||
|
bevy_derive.workspace = true
|
||||||
|
|
||||||
[lints.clippy]
|
[lints.clippy]
|
||||||
too_many_arguments = "allow"
|
too_many_arguments = "allow"
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
use std::{any::TypeId, marker::PhantomData};
|
use std::{any::TypeId, marker::PhantomData};
|
||||||
|
|
||||||
use bevy::app::{App, Plugin};
|
use bevy_app::{App, Plugin};
|
||||||
use bevy::math::Vec2;
|
use bevy_ecs::resource::Resource;
|
||||||
use bevy::prelude::Resource;
|
use bevy_math::Vec2;
|
||||||
|
|
||||||
pub struct ActionPlugin<A: Action>(PhantomData<A>);
|
pub struct ActionPlugin<A: Action>(PhantomData<A>);
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,15 @@
|
|||||||
use core::panic;
|
use core::panic;
|
||||||
|
|
||||||
use bevy::app::{App, Plugin};
|
use bevy_app::{App, Plugin};
|
||||||
use bevy::core_pipeline::core_3d::Camera3d;
|
use bevy_camera::{Camera3d, CameraProjection};
|
||||||
use bevy::ecs::component::Component;
|
use bevy_ecs::{component::Component, schedule::SystemSet};
|
||||||
use bevy::math::{Mat4, Vec3A, Vec4};
|
use bevy_math::{Mat4, Vec3A, Vec4};
|
||||||
use bevy::prelude::SystemSet;
|
// use bevy::prelude::SystemSet;
|
||||||
use bevy::reflect::std_traits::ReflectDefault;
|
#[cfg(feature = "reflect")]
|
||||||
use bevy::reflect::Reflect;
|
use bevy_reflect::std_traits::ReflectDefault;
|
||||||
use bevy::render::camera::CameraProjection;
|
#[cfg(feature = "reflect")]
|
||||||
use bevy::render::extract_component::{ExtractComponent, ExtractComponentPlugin};
|
use bevy_reflect::Reflect;
|
||||||
|
use bevy_render::extract_component::{ExtractComponent, ExtractComponentPlugin};
|
||||||
|
|
||||||
use crate::session::XrTracker;
|
use crate::session::XrTracker;
|
||||||
|
|
||||||
@@ -23,8 +24,9 @@ impl Plugin for XrCameraPlugin {
|
|||||||
#[derive(Clone, Copy, Default, PartialEq, Eq, Debug, Hash, SystemSet)]
|
#[derive(Clone, Copy, Default, PartialEq, Eq, Debug, Hash, SystemSet)]
|
||||||
pub struct XrViewInit;
|
pub struct XrViewInit;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Reflect)]
|
#[derive(Debug, Clone)]
|
||||||
#[reflect(Default)]
|
#[cfg_attr(feature = "reflect", derive(Reflect))]
|
||||||
|
#[cfg_attr(feature = "reflect", reflect(Default))]
|
||||||
pub struct XrProjection {
|
pub struct XrProjection {
|
||||||
pub projection_matrix: Mat4,
|
pub projection_matrix: Mat4,
|
||||||
pub near: f32,
|
pub near: f32,
|
||||||
@@ -83,7 +85,7 @@ impl CameraProjection for XrProjection {
|
|||||||
self.projection_matrix
|
self.projection_matrix
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_clip_from_view_for_sub(&self, _sub_view: &bevy::render::camera::SubCameraView) -> Mat4 {
|
fn get_clip_from_view_for_sub(&self, _sub_view: &bevy_camera::SubCameraView) -> Mat4 {
|
||||||
panic!("sub view not supported for xr camera");
|
panic!("sub view not supported for xr camera");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -194,11 +196,8 @@ pub fn calculate_projection(near_z: f32, fov: Fov) -> Mat4 {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use std::f32::{self, consts::PI};
|
use std::f32::{self, consts::PI};
|
||||||
|
|
||||||
use bevy::{
|
use bevy_math::{Mat4,Vec3A};
|
||||||
math::{Mat4, Vec3A},
|
use bevy_camera::{CameraProjection, PerspectiveProjection};
|
||||||
render::camera::{CameraProjection, PerspectiveProjection},
|
|
||||||
utils::default,
|
|
||||||
};
|
|
||||||
|
|
||||||
const TEST_VALUES: &[(f32, f32)] = &[(0.5, 100.0), (50.0, 200.0)];
|
const TEST_VALUES: &[(f32, f32)] = &[(0.5, 100.0), (50.0, 200.0)];
|
||||||
|
|
||||||
@@ -230,7 +229,7 @@ mod tests {
|
|||||||
fn test_get_frustum_corners_symmetrical() {
|
fn test_get_frustum_corners_symmetrical() {
|
||||||
let control_proj = PerspectiveProjection {
|
let control_proj = PerspectiveProjection {
|
||||||
near: 0.1,
|
near: 0.1,
|
||||||
..default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
let projection = XrProjection {
|
let projection = XrProjection {
|
||||||
@@ -252,7 +251,7 @@ mod tests {
|
|||||||
fn test_get_frustum_corners_symmetrical_far_plane() {
|
fn test_get_frustum_corners_symmetrical_far_plane() {
|
||||||
let control_proj = PerspectiveProjection {
|
let control_proj = PerspectiveProjection {
|
||||||
near: 0.1,
|
near: 0.1,
|
||||||
..default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
let projection = XrProjection {
|
let projection = XrProjection {
|
||||||
|
|||||||
@@ -1,13 +1,21 @@
|
|||||||
use crate::hands::{HandBone, XrHandBoneRadius};
|
use crate::hands::{HandBone, XrHandBoneRadius};
|
||||||
use crate::spaces::XrSpaceLocationFlags;
|
use crate::spaces::XrSpaceLocationFlags;
|
||||||
use bevy::color::palettes::css;
|
use bevy_app::{App, Plugin, PostUpdate};
|
||||||
use bevy::{prelude::*, transform::TransformSystem};
|
use bevy_color::palettes::css;
|
||||||
|
use bevy_color::Srgba;
|
||||||
|
use bevy_ecs::schedule::IntoScheduleConfigs as _;
|
||||||
|
use bevy_ecs::system::Query;
|
||||||
|
use bevy_gizmos::gizmos::Gizmos;
|
||||||
|
use bevy_math::Isometry3d;
|
||||||
|
use bevy_transform::TransformSystems;
|
||||||
|
use bevy_transform::components::GlobalTransform;
|
||||||
|
|
||||||
pub struct HandGizmosPlugin;
|
pub struct HandGizmosPlugin;
|
||||||
impl Plugin for HandGizmosPlugin {
|
impl Plugin for HandGizmosPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.add_systems(
|
app.add_systems(
|
||||||
PostUpdate,
|
PostUpdate,
|
||||||
draw_hand_gizmos.after(TransformSystem::TransformPropagate),
|
draw_hand_gizmos.after(TransformSystems::Propagate),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
use bevy::{
|
|
||||||
ecs::{component::Component, entity::Entity},
|
|
||||||
log::warn,
|
|
||||||
math::bool,
|
|
||||||
prelude::{Bundle, Command, Commands, Deref, DerefMut, Resource, Transform, Visibility, World},
|
|
||||||
};
|
|
||||||
use crate::{session::XrTracker, spaces::XrSpaceLocationFlags};
|
use crate::{session::XrTracker, spaces::XrSpaceLocationFlags};
|
||||||
|
use bevy_camera::visibility::Visibility;
|
||||||
|
use bevy_derive::{Deref, DerefMut};
|
||||||
|
use bevy_ecs::{bundle::Bundle, component::Component, entity::Entity, resource::Resource, system::{Command, Commands}, world::World};
|
||||||
|
use bevy_log::warn;
|
||||||
|
use bevy_math::bool;
|
||||||
|
use bevy_transform::components::Transform;
|
||||||
|
|
||||||
pub const HAND_JOINT_COUNT: usize = 26;
|
pub const HAND_JOINT_COUNT: usize = 26;
|
||||||
|
|
||||||
pub fn spawn_hand_bones<T: Bundle>(
|
pub fn spawn_hand_bones<T: Bundle>(
|
||||||
|
|||||||
@@ -5,4 +5,3 @@ pub mod hand_debug_gizmos;
|
|||||||
pub mod hands;
|
pub mod hands;
|
||||||
pub mod session;
|
pub mod session;
|
||||||
pub mod spaces;
|
pub mod spaces;
|
||||||
pub mod types;
|
|
||||||
|
|||||||
@@ -2,30 +2,45 @@ use std::convert::identity;
|
|||||||
use std::sync::atomic::AtomicBool;
|
use std::sync::atomic::AtomicBool;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use bevy::app::{AppExit, MainScheduleOrder};
|
use bevy_app::{App, AppExit, MainScheduleOrder, Plugin, PostUpdate, PreUpdate};
|
||||||
use bevy::ecs::component::HookContext;
|
use bevy_camera::visibility::Visibility;
|
||||||
use bevy::ecs::schedule::ScheduleLabel;
|
use bevy_derive::Deref;
|
||||||
use bevy::ecs::world::DeferredWorld;
|
use bevy_ecs::component::Component;
|
||||||
use bevy::prelude::*;
|
use bevy_ecs::entity::Entity;
|
||||||
use bevy::render::extract_resource::{ExtractResource, ExtractResourcePlugin};
|
use bevy_ecs::hierarchy::Children;
|
||||||
use bevy::render::{Render, RenderApp, RenderSet};
|
use bevy_ecs::lifecycle::HookContext;
|
||||||
|
use bevy_ecs::message::{Message, MessageReader, MessageWriter};
|
||||||
|
use bevy_ecs::query::{Has, With};
|
||||||
|
use bevy_ecs::resource::Resource;
|
||||||
|
use bevy_ecs::schedule::common_conditions::on_message;
|
||||||
|
use bevy_ecs::schedule::{
|
||||||
|
ExecutorKind, IntoScheduleConfigs as _, Schedule, ScheduleLabel, SystemCondition as _, SystemSet
|
||||||
|
};
|
||||||
|
use bevy_ecs::system::{Local, Query, Res, ResMut};
|
||||||
|
use bevy_ecs::world::DeferredWorld;
|
||||||
|
use bevy_render::extract_resource::{ExtractResource, ExtractResourcePlugin};
|
||||||
|
use bevy_render::{Render, RenderApp, RenderSystems};
|
||||||
|
use bevy_transform::components::{GlobalTransform, Transform};
|
||||||
|
use bevy_transform::TransformSystems;
|
||||||
|
#[cfg(feature="reflect")]
|
||||||
|
use bevy_reflect::Reflect;
|
||||||
|
|
||||||
/// Event sent to instruct backends to create an XR session. Only works when the [`XrState`] is [`Available`](XrState::Available).
|
/// Message sent to instruct backends to create an XR session. Only works when the [`XrState`] is [`Available`](XrState::Available).
|
||||||
#[derive(Event, Clone, Copy, Default)]
|
#[derive(Message, Clone, Copy, Default)]
|
||||||
pub struct XrCreateSessionEvent;
|
pub struct XrCreateSessionMessage;
|
||||||
|
|
||||||
/// A schedule thats ran whenever an [`XrCreateSessionEvent`] is recieved while the [`XrState`] is [`Available`](XrState::Available)
|
/// A schedule thats ran whenever an [`XrCreateSessionMessage`] is recieved while the [`XrState`] is [`Available`](XrState::Available)
|
||||||
#[derive(Clone, Copy, Default, PartialEq, Eq, Debug, Hash, ScheduleLabel)]
|
#[derive(Clone, Copy, Default, PartialEq, Eq, Debug, Hash, ScheduleLabel)]
|
||||||
pub struct XrSessionCreated;
|
pub struct XrSessionCreated;
|
||||||
|
|
||||||
/// Event sent after the XrSession was created.
|
/// Message sent after the XrSession was created.
|
||||||
#[derive(Event, Clone, Copy, Default)]
|
#[derive(Message, Clone, Copy, Default)]
|
||||||
pub struct XrSessionCreatedEvent;
|
pub struct XrSessionCreatedMessage;
|
||||||
|
|
||||||
/// Event sent to instruct backends to destroy an XR session. Only works when the [`XrState`] is [`Exiting`](XrState::Exiting).
|
/// Message sent to instruct backends to destroy an XR session. Only works when the [`XrState`] is [`Exiting`](XrState::Exiting).
|
||||||
/// If you would like to request that a running session be destroyed, send the [`XrRequestExitEvent`] instead.
|
/// If you would like to request that a running session be destroyed, send the [`XrRequestExitMessage`] instead.
|
||||||
#[derive(Event, Clone, Copy, Default)]
|
#[derive(Message, Clone, Copy, Default)]
|
||||||
pub struct XrDestroySessionEvent;
|
pub struct XrDestroySessionMessage;
|
||||||
|
|
||||||
/// Resource flag thats inserted into the world and extracted to the render world to inform any session resources in the render world to drop.
|
/// Resource flag thats inserted into the world and extracted to the render world to inform any session resources in the render world to drop.
|
||||||
#[derive(Resource, Clone, Default)]
|
#[derive(Resource, Clone, Default)]
|
||||||
@@ -35,29 +50,29 @@ pub struct XrDestroySessionRender(pub Arc<AtomicBool>);
|
|||||||
#[derive(Clone, Copy, Default, PartialEq, Eq, Debug, Hash, ScheduleLabel)]
|
#[derive(Clone, Copy, Default, PartialEq, Eq, Debug, Hash, ScheduleLabel)]
|
||||||
pub struct XrPreDestroySession;
|
pub struct XrPreDestroySession;
|
||||||
|
|
||||||
/// Event sent to instruct backends to begin an XR session. Only works when the [`XrState`] is [`Ready`](XrState::Ready).
|
/// Message sent to instruct backends to begin an XR session. Only works when the [`XrState`] is [`Ready`](XrState::Ready).
|
||||||
#[derive(Event, Clone, Copy, Default)]
|
#[derive(Message, Clone, Copy, Default)]
|
||||||
pub struct XrBeginSessionEvent;
|
pub struct XrBeginSessionMessage;
|
||||||
|
|
||||||
/// Schedule thats ran when the XrSession has begun.
|
/// Schedule thats ran when the XrSession has begun.
|
||||||
#[derive(Clone, Copy, Default, PartialEq, Eq, Debug, Hash, ScheduleLabel)]
|
#[derive(Clone, Copy, Default, PartialEq, Eq, Debug, Hash, ScheduleLabel)]
|
||||||
pub struct XrPostSessionBegin;
|
pub struct XrPostSessionBegin;
|
||||||
|
|
||||||
/// Event sent to backends to end an XR session. Only works when the [`XrState`] is [`Stopping`](XrState::Stopping).
|
/// Message sent to backends to end an XR session. Only works when the [`XrState`] is [`Stopping`](XrState::Stopping).
|
||||||
#[derive(Event, Clone, Copy, Default)]
|
#[derive(Message, Clone, Copy, Default)]
|
||||||
pub struct XrEndSessionEvent;
|
pub struct XrEndSessionMessage;
|
||||||
|
|
||||||
/// Schedule thats ran whenever the XrSession is about to end
|
/// Schedule thats ran whenever the XrSession is about to end
|
||||||
#[derive(Clone, Copy, Default, PartialEq, Eq, Debug, Hash, ScheduleLabel)]
|
#[derive(Clone, Copy, Default, PartialEq, Eq, Debug, Hash, ScheduleLabel)]
|
||||||
pub struct XrPreSessionEnd;
|
pub struct XrPreSessionEnd;
|
||||||
|
|
||||||
/// Event that is emitted when the XrSession is fully destroyed
|
/// Message that is emitted when the XrSession is fully destroyed
|
||||||
#[derive(Clone, Copy, Default, PartialEq, Eq, Debug, Hash, Event)]
|
#[derive(Message, Clone, Copy, Default, PartialEq, Eq, Debug, Hash)]
|
||||||
pub struct XrSessionDestroyedEvent;
|
pub struct XrSessionDestroyedMessage;
|
||||||
|
|
||||||
/// Event sent to backends to request the [`XrState`] proceed to [`Exiting`](XrState::Exiting) and for the session to be exited. Can be called at any time a session exists.
|
/// Message sent to backends to request the [`XrState`] proceed to [`Exiting`](XrState::Exiting) and for the session to be exited. Can be called at any time a session exists.
|
||||||
#[derive(Event, Clone, Copy, Default)]
|
#[derive(Message, Clone, Copy, Default)]
|
||||||
pub struct XrRequestExitEvent;
|
pub struct XrRequestExitMessage;
|
||||||
|
|
||||||
/// Schedule ran before [`First`] to handle XR events.
|
/// Schedule ran before [`First`] to handle XR events.
|
||||||
#[derive(Clone, Copy, Default, PartialEq, Eq, Debug, Hash, ScheduleLabel)]
|
#[derive(Clone, Copy, Default, PartialEq, Eq, Debug, Hash, ScheduleLabel)]
|
||||||
@@ -75,13 +90,13 @@ pub enum XrHandleEvents {
|
|||||||
|
|
||||||
/// System sets ran in the render world for XR.
|
/// System sets ran in the render world for XR.
|
||||||
#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy, SystemSet)]
|
#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy, SystemSet)]
|
||||||
pub enum XrRenderSet {
|
pub enum XrRenderSystems {
|
||||||
/// Ran before [`XrRenderSet::PreRender`] but after [`RenderSet::ExtractCommands`].
|
/// Ran before [`XrRenderSet::PreRender`] but after [`RenderSystems::ExtractCommands`].
|
||||||
HandleEvents,
|
HandleEvents,
|
||||||
/// For any XR systems needing to be ran before rendering begins.
|
/// For any XR systems needing to be ran before rendering begins.
|
||||||
/// Ran after [`XrRenderSet::HandleEvents`] but before every render set except [`RenderSet::ExtractCommands`].
|
/// Ran after [`XrRenderSet::HandleEvents`] but before every render set except [`RenderSystems::ExtractCommands`].
|
||||||
PreRender,
|
PreRender,
|
||||||
/// For any XR systems needing to be ran after [`RenderSet::Render`] but before [`RenderSet::Cleanup`].
|
/// For any XR systems needing to be ran after [`RenderSystems::Render`] but before [`RenderSystems::Cleanup`].
|
||||||
PostRender,
|
PostRender,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,7 +112,8 @@ pub struct XrTrackingRoot;
|
|||||||
struct TrackingRootRes(Entity);
|
struct TrackingRootRes(Entity);
|
||||||
|
|
||||||
/// Makes the entity a child of the XrTrackingRoot if the entity has no parent
|
/// Makes the entity a child of the XrTrackingRoot if the entity has no parent
|
||||||
#[derive(Clone, Copy, Hash, PartialEq, Eq, Reflect, Debug, Default, Component)]
|
#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug, Default, Component)]
|
||||||
|
#[cfg_attr(feature = "reflect", derive(Reflect))]
|
||||||
#[component(on_add = on_tracker_add)]
|
#[component(on_add = on_tracker_add)]
|
||||||
pub struct XrTracker;
|
pub struct XrTracker;
|
||||||
fn on_tracker_add(mut world: DeferredWorld, HookContext { entity, .. }: HookContext) {
|
fn on_tracker_add(mut world: DeferredWorld, HookContext { entity, .. }: HookContext) {
|
||||||
@@ -122,15 +138,15 @@ impl Plugin for XrSessionPlugin {
|
|||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.init_resource::<XrDestroySessionRender>();
|
app.init_resource::<XrDestroySessionRender>();
|
||||||
let mut xr_first = Schedule::new(XrFirst);
|
let mut xr_first = Schedule::new(XrFirst);
|
||||||
xr_first.set_executor_kind(bevy::ecs::schedule::ExecutorKind::Simple);
|
xr_first.set_executor_kind(ExecutorKind::SingleThreaded);
|
||||||
app.add_event::<XrCreateSessionEvent>()
|
app.add_message::<XrCreateSessionMessage>()
|
||||||
.add_event::<XrDestroySessionEvent>()
|
.add_message::<XrDestroySessionMessage>()
|
||||||
.add_event::<XrBeginSessionEvent>()
|
.add_message::<XrBeginSessionMessage>()
|
||||||
.add_event::<XrEndSessionEvent>()
|
.add_message::<XrEndSessionMessage>()
|
||||||
.add_event::<XrRequestExitEvent>()
|
.add_message::<XrRequestExitMessage>()
|
||||||
.add_event::<XrStateChanged>()
|
.add_message::<XrStateChanged>()
|
||||||
.add_event::<XrSessionCreatedEvent>()
|
.add_message::<XrSessionCreatedMessage>()
|
||||||
.add_event::<XrSessionDestroyedEvent>()
|
.add_message::<XrSessionDestroyedMessage>()
|
||||||
.init_schedule(XrSessionCreated)
|
.init_schedule(XrSessionCreated)
|
||||||
.init_schedule(XrPreDestroySession)
|
.init_schedule(XrPreDestroySession)
|
||||||
.init_schedule(XrPostSessionBegin)
|
.init_schedule(XrPostSessionBegin)
|
||||||
@@ -150,7 +166,7 @@ impl Plugin for XrSessionPlugin {
|
|||||||
.add_systems(
|
.add_systems(
|
||||||
XrFirst,
|
XrFirst,
|
||||||
exits_session_on_app_exit
|
exits_session_on_app_exit
|
||||||
.run_if(on_event::<AppExit>)
|
.run_if(on_message::<AppExit>)
|
||||||
.run_if(session_created)
|
.run_if(session_created)
|
||||||
.in_set(XrHandleEvents::ExitEvents),
|
.in_set(XrHandleEvents::ExitEvents),
|
||||||
);
|
);
|
||||||
@@ -178,13 +194,13 @@ impl Plugin for XrSessionPlugin {
|
|||||||
.init_resource::<XrRootTransform>()
|
.init_resource::<XrRootTransform>()
|
||||||
.add_systems(
|
.add_systems(
|
||||||
PostUpdate,
|
PostUpdate,
|
||||||
update_root_transform.after(TransformSystem::TransformPropagate),
|
update_root_transform.after(TransformSystems::Propagate),
|
||||||
)
|
)
|
||||||
.add_systems(
|
.add_systems(
|
||||||
XrFirst,
|
XrFirst,
|
||||||
exits_session_on_app_exit
|
exits_session_on_app_exit
|
||||||
.before(XrHandleEvents::ExitEvents)
|
.before(XrHandleEvents::ExitEvents)
|
||||||
.run_if(on_event::<AppExit>.and(session_running)),
|
.run_if(on_message::<AppExit>.and(session_running)),
|
||||||
);
|
);
|
||||||
|
|
||||||
let render_app = app.sub_app_mut(RenderApp);
|
let render_app = app.sub_app_mut(RenderApp);
|
||||||
@@ -194,33 +210,33 @@ impl Plugin for XrSessionPlugin {
|
|||||||
// .init_resource::<XrRootTransform>()
|
// .init_resource::<XrRootTransform>()
|
||||||
.configure_sets(
|
.configure_sets(
|
||||||
Render,
|
Render,
|
||||||
(XrRenderSet::HandleEvents, XrRenderSet::PreRender).chain(),
|
(XrRenderSystems::HandleEvents, XrRenderSystems::PreRender).chain(),
|
||||||
)
|
)
|
||||||
.configure_sets(
|
.configure_sets(
|
||||||
Render,
|
Render,
|
||||||
XrRenderSet::HandleEvents.after(RenderSet::ExtractCommands),
|
XrRenderSystems::HandleEvents.after(RenderSystems::ExtractCommands),
|
||||||
)
|
)
|
||||||
.configure_sets(
|
.configure_sets(
|
||||||
Render,
|
Render,
|
||||||
XrRenderSet::PreRender
|
XrRenderSystems::PreRender
|
||||||
.before(RenderSet::ManageViews)
|
.before(RenderSystems::ManageViews)
|
||||||
.before(RenderSet::PrepareAssets),
|
.before(RenderSystems::PrepareAssets),
|
||||||
)
|
)
|
||||||
.configure_sets(
|
.configure_sets(
|
||||||
Render,
|
Render,
|
||||||
XrRenderSet::PostRender
|
XrRenderSystems::PostRender
|
||||||
.after(RenderSet::Render)
|
.after(RenderSystems::Render)
|
||||||
.before(RenderSet::Cleanup),
|
.before(RenderSystems::Cleanup),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn exits_session_on_app_exit(mut request_exit: EventWriter<XrRequestExitEvent>) {
|
fn exits_session_on_app_exit(mut request_exit: MessageWriter<XrRequestExitMessage>) {
|
||||||
request_exit.write_default();
|
request_exit.write_default();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Event sent by backends whenever [`XrState`] is changed.
|
/// Message sent by backends whenever [`XrState`] is changed.
|
||||||
#[derive(Event, Clone, Copy, Deref)]
|
#[derive(Message, Clone, Copy, Deref)]
|
||||||
pub struct XrStateChanged(pub XrState);
|
pub struct XrStateChanged(pub XrState);
|
||||||
|
|
||||||
/// A resource in the main world and render world representing the current session state.
|
/// A resource in the main world and render world representing the current session state.
|
||||||
@@ -229,17 +245,17 @@ pub struct XrStateChanged(pub XrState);
|
|||||||
pub enum XrState {
|
pub enum XrState {
|
||||||
/// An XR session is not available here
|
/// An XR session is not available here
|
||||||
Unavailable,
|
Unavailable,
|
||||||
/// An XR session is available and ready to be created with an [`XrCreateSessionEvent`].
|
/// An XR session is available and ready to be created with an [`XrCreateSessionMessage`].
|
||||||
Available,
|
Available,
|
||||||
/// An XR session is created but not ready to begin. Backends are not required to use this state.
|
/// An XR session is created but not ready to begin. Backends are not required to use this state.
|
||||||
Idle,
|
Idle,
|
||||||
/// An XR session has been created and is ready to start rendering with an [`XrBeginSessionEvent`].
|
/// An XR session has been created and is ready to start rendering with an [`XrBeginSessionMessage`].
|
||||||
Ready,
|
Ready,
|
||||||
/// The XR session is running and can be stopped with an [`XrEndSessionEvent`].
|
/// The XR session is running and can be stopped with an [`XrEndSessionMessage`].
|
||||||
Running,
|
Running,
|
||||||
/// The runtime has requested that the session should be ended with an [`XrEndSessionEvent`].
|
/// The runtime has requested that the session should be ended with an [`XrEndSessionMessage`].
|
||||||
Stopping,
|
Stopping,
|
||||||
/// The XR session should be destroyed with an [`XrDestroySessionEvent`].
|
/// The XR session should be destroyed with an [`XrDestroySessionMessage`].
|
||||||
Exiting {
|
Exiting {
|
||||||
/// Whether we should automatically restart the session
|
/// Whether we should automatically restart the session
|
||||||
should_restart: bool,
|
should_restart: bool,
|
||||||
@@ -247,11 +263,11 @@ pub enum XrState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn auto_handle_session(
|
pub fn auto_handle_session(
|
||||||
mut state_changed: EventReader<XrStateChanged>,
|
mut state_changed: MessageReader<XrStateChanged>,
|
||||||
mut create_session: EventWriter<XrCreateSessionEvent>,
|
mut create_session: MessageWriter<XrCreateSessionMessage>,
|
||||||
mut begin_session: EventWriter<XrBeginSessionEvent>,
|
mut begin_session: MessageWriter<XrBeginSessionMessage>,
|
||||||
mut end_session: EventWriter<XrEndSessionEvent>,
|
mut end_session: MessageWriter<XrEndSessionMessage>,
|
||||||
mut destroy_session: EventWriter<XrDestroySessionEvent>,
|
mut destroy_session: MessageWriter<XrDestroySessionMessage>,
|
||||||
mut no_auto_restart: Local<bool>,
|
mut no_auto_restart: Local<bool>,
|
||||||
) {
|
) {
|
||||||
for XrStateChanged(state) in state_changed.read() {
|
for XrStateChanged(state) in state_changed.read() {
|
||||||
@@ -290,8 +306,8 @@ pub fn update_root_transform(
|
|||||||
/// A [`Condition`](bevy::ecs::schedule::Condition) that allows the system to run when the xr status changed to a specific [`XrStatus`].
|
/// A [`Condition`](bevy::ecs::schedule::Condition) that allows the system to run when the xr status changed to a specific [`XrStatus`].
|
||||||
pub fn status_changed_to(
|
pub fn status_changed_to(
|
||||||
status: XrState,
|
status: XrState,
|
||||||
) -> impl FnMut(EventReader<XrStateChanged>) -> bool + Clone {
|
) -> impl FnMut(MessageReader<XrStateChanged>) -> bool + Clone {
|
||||||
move |mut reader: EventReader<XrStateChanged>| {
|
move |mut reader: MessageReader<XrStateChanged>| {
|
||||||
reader.read().any(|new_status| new_status.0 == status)
|
reader.read().any(|new_status| new_status.0 == status)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -332,5 +348,4 @@ macro_rules! state_matches {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
use bevy::transform::TransformSystem;
|
|
||||||
pub use state_matches;
|
pub use state_matches;
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
use bevy::{
|
use bevy_camera::visibility::Visibility;
|
||||||
prelude::*,
|
use bevy_derive::{Deref, DerefMut};
|
||||||
render::{extract_component::ExtractComponent, extract_resource::ExtractResource},
|
use bevy_ecs::{component::Component, message::Message, resource::Resource, schedule::SystemSet};
|
||||||
};
|
use bevy_math::Vec3;
|
||||||
|
use bevy_render::{extract_component::ExtractComponent, extract_resource::ExtractResource};
|
||||||
|
use bevy_transform::components::Transform;
|
||||||
|
#[cfg(feature="reflect")]
|
||||||
|
use bevy_reflect::Reflect;
|
||||||
|
|
||||||
use crate::session::XrTracker;
|
use crate::session::XrTracker;
|
||||||
|
|
||||||
@@ -10,11 +14,13 @@ pub struct XrSpaceSyncSet;
|
|||||||
|
|
||||||
/// Any Spaces will be invalid after the owning session exits
|
/// Any Spaces will be invalid after the owning session exits
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
#[derive(Component, Clone, Copy, Hash, PartialEq, Eq, Reflect, Debug, ExtractComponent)]
|
#[derive(Component, Clone, Copy, Hash, PartialEq, Eq, Debug, ExtractComponent)]
|
||||||
|
#[cfg_attr(feature = "reflect", derive(Reflect))]
|
||||||
#[require(XrSpaceLocationFlags, Transform, Visibility, XrTracker)]
|
#[require(XrSpaceLocationFlags, Transform, Visibility, XrTracker)]
|
||||||
pub struct XrSpace(u64);
|
pub struct XrSpace(u64);
|
||||||
|
|
||||||
#[derive(Component, Clone, Copy, Reflect, Debug, ExtractComponent, Default)]
|
#[derive(Component, Clone, Copy, Debug, ExtractComponent, Default)]
|
||||||
|
#[cfg_attr(feature = "reflect", derive(Reflect))]
|
||||||
#[require(XrSpaceVelocityFlags)]
|
#[require(XrSpaceVelocityFlags)]
|
||||||
pub struct XrVelocity {
|
pub struct XrVelocity {
|
||||||
/// Velocity of a space relative to it's reference space
|
/// Velocity of a space relative to it's reference space
|
||||||
@@ -34,32 +40,30 @@ impl XrVelocity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Event, Clone, Copy, Deref, DerefMut)]
|
#[derive(Message, Clone, Copy, Deref, DerefMut)]
|
||||||
pub struct XrDestroySpace(pub XrSpace);
|
pub struct XrDestroySpace(pub XrSpace);
|
||||||
|
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
#[derive(
|
#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug, Component, Deref, DerefMut, ExtractComponent)]
|
||||||
Clone, Copy, Hash, PartialEq, Eq, Reflect, Debug, Component, Deref, DerefMut, ExtractComponent,
|
#[cfg_attr(feature = "reflect", derive(Reflect))]
|
||||||
)]
|
|
||||||
pub struct XrReferenceSpace(pub XrSpace);
|
pub struct XrReferenceSpace(pub XrSpace);
|
||||||
|
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
#[derive(
|
#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug, Resource, Deref, DerefMut, ExtractResource)]
|
||||||
Clone, Copy, Hash, PartialEq, Eq, Reflect, Debug, Resource, Deref, DerefMut, ExtractResource,
|
#[cfg_attr(feature = "reflect", derive(Reflect))]
|
||||||
)]
|
|
||||||
pub struct XrPrimaryReferenceSpace(pub XrReferenceSpace);
|
pub struct XrPrimaryReferenceSpace(pub XrReferenceSpace);
|
||||||
|
|
||||||
#[derive(
|
#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug, Component, ExtractComponent, Default)]
|
||||||
Clone, Copy, Hash, PartialEq, Eq, Reflect, Debug, Component, ExtractComponent, Default,
|
#[cfg_attr(feature = "reflect", derive(Reflect))]
|
||||||
)]
|
|
||||||
pub struct XrSpaceLocationFlags {
|
pub struct XrSpaceLocationFlags {
|
||||||
pub position_tracked: bool,
|
pub position_tracked: bool,
|
||||||
pub rotation_tracked: bool,
|
pub rotation_tracked: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
Clone, Copy, Hash, PartialEq, Eq, Reflect, Debug, Component, ExtractComponent, Default,
|
Clone, Copy, Hash, PartialEq, Eq, Debug, Component, ExtractComponent, Default,
|
||||||
)]
|
)]
|
||||||
|
#[cfg_attr(feature = "reflect", derive(Reflect))]
|
||||||
pub struct XrSpaceVelocityFlags {
|
pub struct XrSpaceVelocityFlags {
|
||||||
pub linear_valid: bool,
|
pub linear_valid: bool,
|
||||||
pub angular_valid: bool,
|
pub angular_valid: bool,
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
use bevy::math::Isometry3d;
|
|
||||||
|
|
||||||
#[deprecated = "Use Isometry3d instead"]
|
|
||||||
pub type XrPose = Isometry3d;
|
|
||||||
@@ -9,12 +9,20 @@ description = "utils for bevy_mod_xr and bevy_mod_openxr"
|
|||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bevy = { workspace = true, features = ["bevy_gizmos"] }
|
# bevy = { workspace = true, features = ["bevy_gizmos"] }
|
||||||
bevy_mod_xr.workspace = true
|
bevy_mod_xr.workspace = true
|
||||||
bevy_mod_openxr.workspace = true
|
bevy_mod_openxr.workspace = true
|
||||||
|
bevy_ecs.workspace=true
|
||||||
|
bevy_app.workspace=true
|
||||||
|
bevy_transform.workspace=true
|
||||||
|
bevy_color.workspace=true
|
||||||
|
bevy_gizmos.workspace=true
|
||||||
|
bevy_log.workspace=true
|
||||||
|
bevy_derive.workspace=true
|
||||||
|
bevy_math.workspace=true
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
bevy = { workspace = true, default-features = true }
|
bevy.workspace = true
|
||||||
|
|
||||||
[target.'cfg(not(target_family = "wasm"))'.dependencies]
|
[target.'cfg(not(target_family = "wasm"))'.dependencies]
|
||||||
openxr.workspace = true
|
openxr.workspace = true
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use bevy::{math::vec3, prelude::*};
|
|||||||
use bevy_mod_openxr::{add_xr_plugins, helper_traits::ToQuat, resources::OxrViews};
|
use bevy_mod_openxr::{add_xr_plugins, helper_traits::ToQuat, resources::OxrViews};
|
||||||
use bevy_mod_xr::session::XrTrackingRoot;
|
use bevy_mod_xr::session::XrTrackingRoot;
|
||||||
use bevy_xr_utils::xr_utils_actions::{
|
use bevy_xr_utils::xr_utils_actions::{
|
||||||
ActiveSet, XRUtilsAction, XRUtilsActionSet, XRUtilsActionState, XRUtilsActionSystemSet,
|
ActiveSet, XRUtilsAction, XRUtilsActionSet, XRUtilsActionState, XRUtilsActionSystems,
|
||||||
XRUtilsActionsPlugin, XRUtilsBinding,
|
XRUtilsActionsPlugin, XRUtilsBinding,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -14,7 +14,7 @@ fn main() {
|
|||||||
.add_systems(Startup, setup_scene)
|
.add_systems(Startup, setup_scene)
|
||||||
.add_systems(
|
.add_systems(
|
||||||
Startup,
|
Startup,
|
||||||
create_action_entities.before(XRUtilsActionSystemSet::CreateEvents),
|
create_action_entities.before(XRUtilsActionSystems::CreateEvents),
|
||||||
)
|
)
|
||||||
.add_plugins(XRUtilsActionsPlugin)
|
.add_plugins(XRUtilsActionsPlugin)
|
||||||
.add_systems(Update, read_action_with_marker_component)
|
.add_systems(Update, read_action_with_marker_component)
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use bevy::prelude::*;
|
|||||||
use bevy_mod_openxr::add_xr_plugins;
|
use bevy_mod_openxr::add_xr_plugins;
|
||||||
use bevy_xr_utils::transform_utils::{self, SnapToPosition, SnapToRotation};
|
use bevy_xr_utils::transform_utils::{self, SnapToPosition, SnapToRotation};
|
||||||
use bevy_xr_utils::xr_utils_actions::{
|
use bevy_xr_utils::xr_utils_actions::{
|
||||||
ActiveSet, XRUtilsAction, XRUtilsActionSet, XRUtilsActionState, XRUtilsActionSystemSet,
|
ActiveSet, XRUtilsAction, XRUtilsActionSet, XRUtilsActionState, XRUtilsActionSystems,
|
||||||
XRUtilsActionsPlugin, XRUtilsBinding,
|
XRUtilsActionsPlugin, XRUtilsBinding,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -17,15 +17,15 @@ fn main() -> AppExit {
|
|||||||
.add_plugins(XRUtilsActionsPlugin)
|
.add_plugins(XRUtilsActionsPlugin)
|
||||||
.add_systems(
|
.add_systems(
|
||||||
Startup,
|
Startup,
|
||||||
create_action_entities.before(XRUtilsActionSystemSet::CreateEvents),
|
create_action_entities.before(XRUtilsActionSystems::CreateEvents),
|
||||||
)
|
)
|
||||||
.add_systems(
|
.add_systems(
|
||||||
Update,
|
Update,
|
||||||
send_look_at_red_cube_event.after(XRUtilsActionSystemSet::SyncActionStates),
|
send_look_at_red_cube_event.after(XRUtilsActionSystems::SyncActionStates),
|
||||||
)
|
)
|
||||||
.add_systems(
|
.add_systems(
|
||||||
Update,
|
Update,
|
||||||
send_recenter.after(XRUtilsActionSystemSet::SyncActionStates),
|
send_recenter.after(XRUtilsActionSystems::SyncActionStates),
|
||||||
)
|
)
|
||||||
.insert_resource(AmbientLight {
|
.insert_resource(AmbientLight {
|
||||||
brightness: 500.0,
|
brightness: 500.0,
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
use bevy::{color::palettes::css, prelude::*};
|
use bevy_app::{App, Plugin, PostUpdate};
|
||||||
|
use bevy_color::palettes::css;
|
||||||
|
use bevy_ecs::{component::Component, query::With, schedule::IntoScheduleConfigs as _, system::Query};
|
||||||
|
use bevy_gizmos::gizmos::Gizmos;
|
||||||
|
use bevy_transform::{TransformSystems, components::{GlobalTransform, Transform}};
|
||||||
|
|
||||||
#[derive(Clone, Copy, Component)]
|
#[derive(Clone, Copy, Component)]
|
||||||
#[require(Transform)]
|
#[require(Transform)]
|
||||||
@@ -8,10 +12,7 @@ pub struct GenericTrackerGizmoPlugin;
|
|||||||
|
|
||||||
impl Plugin for GenericTrackerGizmoPlugin {
|
impl Plugin for GenericTrackerGizmoPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.add_systems(
|
app.add_systems(PostUpdate, draw_gizmos.after(TransformSystems::Propagate));
|
||||||
PostUpdate,
|
|
||||||
draw_gizmos.after(TransformSystem::TransformPropagate),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
use std::convert::identity;
|
use std::convert::identity;
|
||||||
|
|
||||||
use bevy::prelude::*;
|
use bevy_app::{App, Plugin, PreUpdate};
|
||||||
|
use bevy_derive::{Deref, DerefMut};
|
||||||
|
use bevy_ecs::{component::Component, entity::Entity, query::With, resource::Resource, schedule::{IntoScheduleConfigs as _, common_conditions::resource_exists}, system::{Commands, Query, Res, ResMut}};
|
||||||
|
use bevy_log::{error, info};
|
||||||
use bevy_mod_openxr::{
|
use bevy_mod_openxr::{
|
||||||
resources::{OxrInstance, OxrSystemId},
|
resources::{OxrInstance, OxrSystemId},
|
||||||
session::OxrSession,
|
session::OxrSession,
|
||||||
|
|||||||
@@ -1,4 +1,13 @@
|
|||||||
use bevy::prelude::*;
|
use bevy_app::{App, Plugin, PreUpdate, Startup};
|
||||||
|
use bevy_ecs::{
|
||||||
|
component::Component,
|
||||||
|
message::MessageWriter,
|
||||||
|
query::{With, Without},
|
||||||
|
resource::Resource,
|
||||||
|
schedule::IntoScheduleConfigs as _,
|
||||||
|
system::{Commands, Query, Res},
|
||||||
|
};
|
||||||
|
use bevy_math::{EulerRot, Isometry3d, Quat};
|
||||||
use bevy_mod_openxr::{
|
use bevy_mod_openxr::{
|
||||||
action_binding::OxrSuggestActionBinding,
|
action_binding::OxrSuggestActionBinding,
|
||||||
action_set_attaching::OxrAttachActionSet,
|
action_set_attaching::OxrAttachActionSet,
|
||||||
@@ -13,6 +22,7 @@ use bevy_mod_xr::{
|
|||||||
session::{XrSessionCreated, XrTracker, XrTrackingRoot},
|
session::{XrSessionCreated, XrTracker, XrTrackingRoot},
|
||||||
spaces::{XrPrimaryReferenceSpace, XrReferenceSpace, XrSpaceSyncSet},
|
spaces::{XrPrimaryReferenceSpace, XrReferenceSpace, XrSpaceSyncSet},
|
||||||
};
|
};
|
||||||
|
use bevy_transform::components::Transform;
|
||||||
use openxr::Posef;
|
use openxr::Posef;
|
||||||
|
|
||||||
//exernal api
|
//exernal api
|
||||||
@@ -203,14 +213,9 @@ fn spawn_tracking_rig(
|
|||||||
) {
|
) {
|
||||||
//head
|
//head
|
||||||
let head_space = session
|
let head_space = session
|
||||||
.create_reference_space(openxr::ReferenceSpaceType::VIEW, Transform::IDENTITY)
|
.create_reference_space(openxr::ReferenceSpaceType::VIEW, Isometry3d::IDENTITY)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
cmds.spawn((
|
cmds.spawn((Transform::default(), XrTracker, HeadXRSpace(head_space)));
|
||||||
Transform::default(),
|
|
||||||
Visibility::default(),
|
|
||||||
XrTracker,
|
|
||||||
HeadXRSpace(head_space),
|
|
||||||
));
|
|
||||||
// let local_floor = cmds.spawn((SpatialBundle::default(), LocalFloor)).id();
|
// let local_floor = cmds.spawn((SpatialBundle::default(), LocalFloor)).id();
|
||||||
|
|
||||||
let left_space = session
|
let left_space = session
|
||||||
@@ -227,7 +232,7 @@ fn spawn_tracking_rig(
|
|||||||
//TODO figure out how to make these better, specifically not be controller specific
|
//TODO figure out how to make these better, specifically not be controller specific
|
||||||
pub fn suggest_action_bindings(
|
pub fn suggest_action_bindings(
|
||||||
actions: Res<ControllerActions>,
|
actions: Res<ControllerActions>,
|
||||||
mut bindings: EventWriter<OxrSuggestActionBinding>,
|
mut bindings: MessageWriter<OxrSuggestActionBinding>,
|
||||||
) {
|
) {
|
||||||
bindings.write(OxrSuggestActionBinding {
|
bindings.write(OxrSuggestActionBinding {
|
||||||
action: actions.left.as_raw(),
|
action: actions.left.as_raw(),
|
||||||
@@ -241,11 +246,11 @@ pub fn suggest_action_bindings(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sync_actions(actions: Res<ControllerActions>, mut sync: EventWriter<OxrSyncActionSet>) {
|
fn sync_actions(actions: Res<ControllerActions>, mut sync: MessageWriter<OxrSyncActionSet>) {
|
||||||
sync.write(OxrSyncActionSet(actions.set.clone()));
|
sync.write(OxrSyncActionSet(actions.set.clone()));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn attach_set(actions: Res<ControllerActions>, mut attach: EventWriter<OxrAttachActionSet>) {
|
fn attach_set(actions: Res<ControllerActions>, mut attach: MessageWriter<OxrAttachActionSet>) {
|
||||||
attach.write(OxrAttachActionSet(actions.set.clone()));
|
attach.write(OxrAttachActionSet(actions.set.clone()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,32 +1,36 @@
|
|||||||
use bevy::prelude::*;
|
use bevy_app::{App, Plugin, PostUpdate};
|
||||||
|
use bevy_ecs::{message::{Message, MessageReader}, query::With, system::{Query, ResMut}};
|
||||||
|
use bevy_log::debug;
|
||||||
|
use bevy_math::{Quat, Vec3};
|
||||||
use bevy_mod_openxr::{
|
use bevy_mod_openxr::{
|
||||||
helper_traits::{ToQuat, ToVec3},
|
helper_traits::{ToQuat, ToVec3},
|
||||||
resources::OxrViews,
|
resources::OxrViews,
|
||||||
};
|
};
|
||||||
use bevy_mod_xr::session::XrTrackingRoot;
|
use bevy_mod_xr::session::XrTrackingRoot;
|
||||||
|
use bevy_transform::components::Transform;
|
||||||
|
|
||||||
pub struct TransformUtilitiesPlugin;
|
pub struct TransformUtilitiesPlugin;
|
||||||
|
|
||||||
impl Plugin for TransformUtilitiesPlugin {
|
impl Plugin for TransformUtilitiesPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.add_event::<SnapToRotation>();
|
app.add_message::<SnapToRotation>();
|
||||||
app.add_event::<SnapToPosition>();
|
app.add_message::<SnapToPosition>();
|
||||||
app.add_systems(PostUpdate, handle_transform_events);
|
app.add_systems(PostUpdate, handle_transform_events);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//events
|
//events
|
||||||
#[derive(Event, Debug)]
|
#[derive(Message, Debug)]
|
||||||
pub struct SnapToRotation(pub Quat);
|
pub struct SnapToRotation(pub Quat);
|
||||||
|
|
||||||
#[derive(Event, Debug)]
|
#[derive(Message, Debug)]
|
||||||
pub struct SnapToPosition(pub Vec3);
|
pub struct SnapToPosition(pub Vec3);
|
||||||
|
|
||||||
pub fn handle_transform_events(
|
pub fn handle_transform_events(
|
||||||
mut root_query: Query<&mut Transform, With<XrTrackingRoot>>,
|
mut root_query: Query<&mut Transform, With<XrTrackingRoot>>,
|
||||||
views: ResMut<OxrViews>,
|
views: ResMut<OxrViews>,
|
||||||
mut position_reader: EventReader<SnapToPosition>,
|
mut position_reader: MessageReader<SnapToPosition>,
|
||||||
mut rotation_reader: EventReader<SnapToRotation>,
|
mut rotation_reader: MessageReader<SnapToRotation>,
|
||||||
) {
|
) {
|
||||||
let result = root_query.single_mut();
|
let result = root_query.single_mut();
|
||||||
match result {
|
match result {
|
||||||
@@ -52,11 +56,11 @@ pub fn handle_transform_events(
|
|||||||
let root_rot = root_transform.rotation;
|
let root_rot = root_transform.rotation;
|
||||||
let view_global_rotation = root_rot.mul_quat(view_rot).normalize();
|
let view_global_rotation = root_rot.mul_quat(view_rot).normalize();
|
||||||
let (global_view_yaw, _pitch, _roll) =
|
let (global_view_yaw, _pitch, _roll) =
|
||||||
view_global_rotation.to_euler(bevy::math::EulerRot::YXZ);
|
view_global_rotation.to_euler(bevy_math::EulerRot::YXZ);
|
||||||
let up = Vec3::Y;
|
let up = Vec3::Y;
|
||||||
for rotation in rotation_reader.read() {
|
for rotation in rotation_reader.read() {
|
||||||
let (target_yaw, _pitch, _roll) =
|
let (target_yaw, _pitch, _roll) =
|
||||||
rotation.0.normalize().to_euler(bevy::math::EulerRot::YXZ);
|
rotation.0.normalize().to_euler(bevy_math::EulerRot::YXZ);
|
||||||
let diff_yaw = target_yaw - global_view_yaw;
|
let diff_yaw = target_yaw - global_view_yaw;
|
||||||
|
|
||||||
//build a rotation quat?
|
//build a rotation quat?
|
||||||
|
|||||||
@@ -53,7 +53,9 @@
|
|||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//!
|
//!
|
||||||
use bevy::prelude::*;
|
use bevy_app::{App, Plugin, PreUpdate, Startup, Update};
|
||||||
|
use bevy_ecs::{component::Component, entity::Entity, hierarchy::Children, message::MessageWriter, query::With, schedule::{IntoScheduleConfigs as _, SystemSet}, system::{Commands, Query, Res, ResMut}};
|
||||||
|
use bevy_log::info;
|
||||||
use bevy_mod_openxr::{
|
use bevy_mod_openxr::{
|
||||||
action_binding::OxrSuggestActionBinding,
|
action_binding::OxrSuggestActionBinding,
|
||||||
action_set_attaching::OxrAttachActionSet,
|
action_set_attaching::OxrAttachActionSet,
|
||||||
@@ -71,16 +73,16 @@ impl Plugin for XRUtilsActionsPlugin {
|
|||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.configure_sets(
|
app.configure_sets(
|
||||||
Startup,
|
Startup,
|
||||||
XRUtilsActionSystemSet::CreateEvents.run_if(openxr_session_available),
|
XRUtilsActionSystems::CreateEvents.run_if(openxr_session_available),
|
||||||
);
|
);
|
||||||
app.configure_sets(
|
app.configure_sets(
|
||||||
PreUpdate,
|
PreUpdate,
|
||||||
XRUtilsActionSystemSet::SyncActionStates.run_if(openxr_session_running),
|
XRUtilsActionSystems::SyncActionStates.run_if(openxr_session_running),
|
||||||
);
|
);
|
||||||
app.add_systems(
|
app.add_systems(
|
||||||
Startup,
|
Startup,
|
||||||
create_openxr_events
|
create_openxr_events
|
||||||
.in_set(XRUtilsActionSystemSet::CreateEvents)
|
.in_set(XRUtilsActionSystems::CreateEvents)
|
||||||
.run_if(openxr_session_available),
|
.run_if(openxr_session_available),
|
||||||
);
|
);
|
||||||
app.add_systems(
|
app.add_systems(
|
||||||
@@ -91,21 +93,21 @@ impl Plugin for XRUtilsActionsPlugin {
|
|||||||
PreUpdate,
|
PreUpdate,
|
||||||
sync_and_update_action_states_f32
|
sync_and_update_action_states_f32
|
||||||
.run_if(openxr_session_running)
|
.run_if(openxr_session_running)
|
||||||
.in_set(XRUtilsActionSystemSet::SyncActionStates)
|
.in_set(XRUtilsActionSystems::SyncActionStates)
|
||||||
.after(OxrActionSetSyncSet),
|
.after(OxrActionSetSyncSet),
|
||||||
);
|
);
|
||||||
app.add_systems(
|
app.add_systems(
|
||||||
PreUpdate,
|
PreUpdate,
|
||||||
sync_and_update_action_states_bool
|
sync_and_update_action_states_bool
|
||||||
.run_if(openxr_session_running)
|
.run_if(openxr_session_running)
|
||||||
.in_set(XRUtilsActionSystemSet::SyncActionStates)
|
.in_set(XRUtilsActionSystems::SyncActionStates)
|
||||||
.after(OxrActionSetSyncSet),
|
.after(OxrActionSetSyncSet),
|
||||||
);
|
);
|
||||||
app.add_systems(
|
app.add_systems(
|
||||||
PreUpdate,
|
PreUpdate,
|
||||||
sync_and_update_action_states_vector
|
sync_and_update_action_states_vector
|
||||||
.run_if(openxr_session_running)
|
.run_if(openxr_session_running)
|
||||||
.in_set(XRUtilsActionSystemSet::SyncActionStates)
|
.in_set(XRUtilsActionSystems::SyncActionStates)
|
||||||
.after(OxrActionSetSyncSet),
|
.after(OxrActionSetSyncSet),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -116,8 +118,8 @@ fn create_openxr_events(
|
|||||||
actions_query: Query<(&XRUtilsAction, &Children)>,
|
actions_query: Query<(&XRUtilsAction, &Children)>,
|
||||||
bindings_query: Query<&XRUtilsBinding>,
|
bindings_query: Query<&XRUtilsBinding>,
|
||||||
instance: ResMut<OxrInstance>,
|
instance: ResMut<OxrInstance>,
|
||||||
mut binding_writer: EventWriter<OxrSuggestActionBinding>,
|
mut binding_writer: MessageWriter<OxrSuggestActionBinding>,
|
||||||
mut attach_writer: EventWriter<OxrAttachActionSet>,
|
mut attach_writer: MessageWriter<OxrAttachActionSet>,
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
) {
|
) {
|
||||||
//lets create some sets!
|
//lets create some sets!
|
||||||
@@ -131,7 +133,7 @@ fn create_openxr_events(
|
|||||||
commands.entity(id).insert(oxr_action_set);
|
commands.entity(id).insert(oxr_action_set);
|
||||||
|
|
||||||
//since the actions are made from the sets lets go
|
//since the actions are made from the sets lets go
|
||||||
for child in children.iter() {
|
for child in children.iter().copied() {
|
||||||
//first get the action entity and stuff
|
//first get the action entity and stuff
|
||||||
let (create_action, bindings) = actions_query.get(child).unwrap();
|
let (create_action, bindings) = actions_query.get(child).unwrap();
|
||||||
//lets create dat action
|
//lets create dat action
|
||||||
@@ -158,7 +160,7 @@ fn create_openxr_events(
|
|||||||
}),
|
}),
|
||||||
));
|
));
|
||||||
//since we need actions for bindings lets go!!
|
//since we need actions for bindings lets go!!
|
||||||
for bind in bindings.iter() {
|
for bind in bindings.iter().copied() {
|
||||||
//interaction profile
|
//interaction profile
|
||||||
//get the binding entity and stuff
|
//get the binding entity and stuff
|
||||||
let create_binding = bindings_query.get(bind).unwrap();
|
let create_binding = bindings_query.get(bind).unwrap();
|
||||||
@@ -197,7 +199,7 @@ fn create_openxr_events(
|
|||||||
}),
|
}),
|
||||||
));
|
));
|
||||||
//since we need actions for bindings lets go!!
|
//since we need actions for bindings lets go!!
|
||||||
for bind in bindings.iter() {
|
for bind in bindings.iter().copied() {
|
||||||
//interaction profile
|
//interaction profile
|
||||||
//get the binding entity and stuff
|
//get the binding entity and stuff
|
||||||
let create_binding = bindings_query.get(bind).unwrap();
|
let create_binding = bindings_query.get(bind).unwrap();
|
||||||
@@ -236,7 +238,7 @@ fn create_openxr_events(
|
|||||||
}),
|
}),
|
||||||
));
|
));
|
||||||
//since we need actions for bindings lets go!!
|
//since we need actions for bindings lets go!!
|
||||||
for bind in bindings.iter() {
|
for bind in bindings.iter().copied() {
|
||||||
//interaction profile
|
//interaction profile
|
||||||
//get the binding entity and stuff
|
//get the binding entity and stuff
|
||||||
let create_binding = bindings_query.get(bind).unwrap();
|
let create_binding = bindings_query.get(bind).unwrap();
|
||||||
@@ -260,7 +262,7 @@ fn create_openxr_events(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn sync_active_action_sets(
|
fn sync_active_action_sets(
|
||||||
mut sync_set: EventWriter<OxrSyncActionSet>,
|
mut sync_set: MessageWriter<OxrSyncActionSet>,
|
||||||
active_action_set_query: Query<&XRUtilsActionSetReference, With<ActiveSet>>,
|
active_action_set_query: Query<&XRUtilsActionSetReference, With<ActiveSet>>,
|
||||||
) {
|
) {
|
||||||
for set in &active_action_set_query {
|
for set in &active_action_set_query {
|
||||||
@@ -344,7 +346,7 @@ fn sync_and_update_action_states_vector(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy, SystemSet)]
|
#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy, SystemSet)]
|
||||||
pub enum XRUtilsActionSystemSet {
|
pub enum XRUtilsActionSystems {
|
||||||
/// Runs in Startup
|
/// Runs in Startup
|
||||||
CreateEvents,
|
CreateEvents,
|
||||||
/// Runs in PreUpdate
|
/// Runs in PreUpdate
|
||||||
|
|||||||
Reference in New Issue
Block a user