From 81b65c4718fd7934ac6013e269101f04eeb77d60 Mon Sep 17 00:00:00 2001 From: Schmarni Date: Mon, 21 Oct 2024 22:30:50 +0200 Subject: [PATCH 1/4] move spawn_hand_bones from openxr to xr and add spawn handtracker command Signed-off-by: Schmarni --- .../src/openxr/features/handtracking.rs | 108 +++++++++--------- crates/bevy_xr/src/hands.rs | 78 ++++++++++++- 2 files changed, 128 insertions(+), 58 deletions(-) diff --git a/crates/bevy_openxr/src/openxr/features/handtracking.rs b/crates/bevy_openxr/src/openxr/features/handtracking.rs index 57726e1..6c0cff6 100644 --- a/crates/bevy_openxr/src/openxr/features/handtracking.rs +++ b/crates/bevy_openxr/src/openxr/features/handtracking.rs @@ -1,6 +1,9 @@ use bevy::prelude::*; -use bevy_mod_xr::hands::{HandBone, HandBoneRadius}; -use bevy_mod_xr::hands::{LeftHand, RightHand, XrHandBoneEntities, HAND_JOINT_COUNT}; +use bevy_mod_xr::hands::{ + spawn_hand_bones, HandBone, HandBoneRadius, HandSide, SpawnHandTracker, + SpawnHandTrackerCommandExecutor, +}; +use bevy_mod_xr::hands::{LeftHand, RightHand, XrHandBoneEntities}; use bevy_mod_xr::session::{XrPreDestroySession, XrSessionCreated, XrTrackingRoot}; use bevy_mod_xr::spaces::{ XrPrimaryReferenceSpace, XrReferenceSpace, XrSpaceLocationFlags, XrSpaceVelocityFlags, @@ -9,11 +12,11 @@ use bevy_mod_xr::spaces::{ use openxr::{SpaceLocationFlags, SpaceVelocityFlags}; use crate::helper_traits::ToVec3; -use crate::openxr_session_running; use crate::resources::OxrFrameState; use crate::resources::Pipelined; use crate::session::OxrSession; use crate::spaces::{OxrSpaceLocationFlags, OxrSpaceVelocityFlags}; +use crate::{openxr_session_available, openxr_session_running}; pub struct HandTrackingPlugin { default_hands: bool, @@ -33,42 +36,24 @@ impl Plugin for HandTrackingPlugin { app.add_systems(XrPreDestroySession, clean_up_default_hands) .add_systems(XrSessionCreated, spawn_default_hands); } + app.add_systems(Startup, set_spawn_executor.run_if(openxr_session_available)); } } -pub fn spawn_hand_bones( - cmds: &mut Commands, - bundle: T, -) -> [Entity; HAND_JOINT_COUNT] { - let mut bones: [Entity; HAND_JOINT_COUNT] = [Entity::PLACEHOLDER; HAND_JOINT_COUNT]; - // screw you clippy, i don't see a better way to init this array - #[allow(clippy::needless_range_loop)] - for bone in HandBone::get_all_bones().into_iter() { - bones[bone as usize] = cmds - .spawn(( - SpatialBundle::default(), - bone, - HandBoneRadius(0.0), - OxrSpaceLocationFlags(openxr::SpaceLocationFlags::default()), - XrSpaceLocationFlags::default(), - )) - .insert(bundle.clone()) - .id(); - } - bones +fn set_spawn_executor(mut cmds: Commands) { + cmds.insert_resource(SpawnHandTrackerCommandExecutor(handle_tracker_spawn)) } -fn spawn_default_hands( - mut cmds: Commands, - session: Res, - root: Query>, -) { - debug!("spawning default hands"); - let Ok(root) = root.get_single() else { - error!("unable to get tracking root, skipping hand creation"); +fn handle_tracker_spawn(world: &mut World, tracker: Entity, side: HandSide) { + let Some(session) = world.get_resource_mut::() else { + error!("unable to get session while creating hand tracker"); return; }; - let tracker_left = match session.create_hand_tracker(openxr::HandEXT::LEFT) { + debug!("spawning hand"); + let oxr_tracker = match session.create_hand_tracker(match side { + HandSide::Left => openxr::HandEXT::LEFT, + HandSide::Right => openxr::HandEXT::RIGHT, + }) { Ok(t) => t, Err(openxr::sys::Result::ERROR_EXTENSION_NOT_PRESENT) => { warn!("Handtracking Extension not loaded, Unable to create Handtracker!"); @@ -79,33 +64,44 @@ fn spawn_default_hands( return; } }; - let tracker_right = match session.create_hand_tracker(openxr::HandEXT::RIGHT) { - Ok(t) => t, - Err(openxr::sys::Result::ERROR_EXTENSION_NOT_PRESENT) => { - warn!("Handtracking Extension not loaded, Unable to create Handtracker!"); - return; - } - Err(err) => { - warn!("Error while creating Handtracker: {}", err.to_string()); - return; - } + + world + .entity_mut(tracker) + .insert(OxrHandTracker(oxr_tracker)); +} + +fn spawn_default_hands(mut cmds: Commands, root: Query>) { + let Ok(root) = root.get_single() else { + error!("unable to get tracking root, skipping handtracker creation"); + return; }; - let left_bones = spawn_hand_bones(&mut cmds, (DefaultHandBone, LeftHand)); - let right_bones = spawn_hand_bones(&mut cmds, (DefaultHandBone, RightHand)); + debug!("spawning default hands"); + let left_bones = spawn_hand_bones(&mut cmds, |_| { + ( + DefaultHandBone, + LeftHand, + OxrSpaceLocationFlags(openxr::SpaceLocationFlags::default()), + ) + }); + let right_bones = spawn_hand_bones(&mut cmds, |_| { + ( + DefaultHandBone, + RightHand, + OxrSpaceLocationFlags(openxr::SpaceLocationFlags::default()), + ) + }); cmds.entity(root).push_children(&left_bones); cmds.entity(root).push_children(&right_bones); - cmds.spawn(( - DefaultHandTracker, - OxrHandTracker(tracker_left), - XrHandBoneEntities(left_bones), - LeftHand, - )); - cmds.spawn(( - DefaultHandTracker, - OxrHandTracker(tracker_right), - XrHandBoneEntities(right_bones), - RightHand, - )); + cmds.push(SpawnHandTracker { + joints: XrHandBoneEntities(left_bones), + tracker_bundle: DefaultHandTracker, + side: HandSide::Left, + }); + cmds.push(SpawnHandTracker { + joints: XrHandBoneEntities(right_bones), + tracker_bundle: DefaultHandTracker, + side: HandSide::Right, + }); } #[derive(Component, Clone, Copy)] diff --git a/crates/bevy_xr/src/hands.rs b/crates/bevy_xr/src/hands.rs index 82e400a..17a6fd5 100644 --- a/crates/bevy_xr/src/hands.rs +++ b/crates/bevy_xr/src/hands.rs @@ -1,16 +1,50 @@ use bevy::{ - ecs::{component::Component, entity::Entity}, + app::Plugin, + ecs::{component::Component, entity::Entity, world::Command}, + hierarchy::BuildWorldChildren, + log::{error, warn}, math::bool, - prelude::{Deref, DerefMut}, + prelude::{Bundle, Commands, Deref, DerefMut, Resource, SpatialBundle, With, World}, +}; + +use crate::{ + session::{XrSessionCreated, XrTrackingRoot}, + spaces::XrSpaceLocationFlags, }; pub const HAND_JOINT_COUNT: usize = 26; +pub fn spawn_hand_bones( + cmds: &mut Commands, + mut get_bundle: impl FnMut(HandBone) -> T, +) -> [Entity; HAND_JOINT_COUNT] { + let mut bones: [Entity; HAND_JOINT_COUNT] = [Entity::PLACEHOLDER; HAND_JOINT_COUNT]; + for bone in HandBone::get_all_bones().into_iter() { + bones[bone as usize] = cmds + .spawn(( + SpatialBundle::default(), + bone, + HandBoneRadius(0.0), + XrSpaceLocationFlags::default(), + )) + .insert((get_bundle)(bone)) + .id(); + } + bones +} + +#[derive(Clone, Copy, Component, Debug)] +pub enum HandSide { + Left, + Right, +} + #[derive(Clone, Copy, Component, Debug)] pub struct LeftHand; #[derive(Clone, Copy, Component, Debug)] pub struct RightHand; +/// Hand Joint Entities orderd #[derive(Deref, DerefMut, Component, Clone, Copy)] pub struct XrHandBoneEntities(pub [Entity; HAND_JOINT_COUNT]); @@ -141,3 +175,43 @@ impl HandBone { ] } } + +/// Use by a backend to run custom logic when spawning a hand tracker +#[derive(Resource)] +pub struct SpawnHandTrackerCommandExecutor(pub fn(&mut World, Entity, HandSide)); + +/// `tracker_bundle` is inserted after the backend specific code is run +pub struct SpawnHandTracker { + pub joints: XrHandBoneEntities, + pub tracker_bundle: B, + pub side: HandSide, +} + +impl Command for SpawnHandTracker { + fn apply(self, world: &mut bevy::prelude::World) { + let Some(executor) = world.remove_resource::() else { + warn!("no SpawnHandTracker executor defined, skipping handtracker creation"); + return; + }; + let Ok(root) = world + .query_filtered::>() + .get_single(world) + else { + error!("unable to get tracking root, skipping handtracker creation"); + return; + }; + let mut tracker = world.spawn(self.joints); + match &self.side { + HandSide::Left => tracker.insert(LeftHand), + HandSide::Right => tracker.insert(LeftHand), + }; + let tracker = tracker.id(); + world.entity_mut(root).push_children(&[tracker]); + executor.0(world, tracker, self.side); + if let Some(mut tracker) = world.get_entity_mut(tracker) { + tracker.insert(self.side); + tracker.insert(self.tracker_bundle); + } + world.insert_resource(executor); + } +} From da659899d4ef06b24813c9377dd7dd947175e77a Mon Sep 17 00:00:00 2001 From: Schmarni Date: Mon, 21 Oct 2024 23:18:30 +0200 Subject: [PATCH 2/4] add simple ci and allow annoying lints Signed-off-by: Schmarni --- .github/workflows/ci.yaml | 51 +++++++++++++++++++++++++++++++++ crates/bevy_openxr/Cargo.toml | 4 +++ crates/bevy_webxr/Cargo.toml | 4 +++ crates/bevy_xr/Cargo.toml | 4 +++ crates/bevy_xr/src/hands.rs | 3 +- crates/bevy_xr_utils/Cargo.toml | 4 +++ 6 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/ci.yaml diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..2cb3cb6 --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,51 @@ +name: CI +on: + push: + branches: + - main + pull_request: + workflow_dispatch: + +jobs: + check_native: + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest] + + name: Check ${{ matrix.os }} + runs-on: ${{ matrix.os }} + + env: + CARGO_TERM_COLOR: always + + steps: + - uses: actions/checkout@v4 + + - run: rustup toolchain install stable --profile minimal --no-self-update + + - uses: ./ + with: + workspaces: . + + - run: cargo check + working-directory: . + + check_wasm: + name: Check Wasm + runs-on: ubuntu-latest + + env: + CARGO_TERM_COLOR: always + + steps: + - uses: actions/checkout@v4 + + - run: rustup toolchain install stable --profile minimal --target wasm32-unknown-unknown --no-self-update + + - uses: ./ + with: + workspaces: . + + - run: cargo check --target wasm32-unknown-unknown + working-directory: . diff --git a/crates/bevy_openxr/Cargo.toml b/crates/bevy_openxr/Cargo.toml index 2b885b8..514ee8d 100644 --- a/crates/bevy_openxr/Cargo.toml +++ b/crates/bevy_openxr/Cargo.toml @@ -43,3 +43,7 @@ wgpu = { version = "0.20", features = ["vulkan-portability"] } openxr = { version = "0.18.0", features = ["mint", "static"] } winapi = { version = "0.3.9", optional = true } d3d12 = { version = "0.20", features = ["libloading"], optional = true } + +[lints.clippy] +too_many_arguments = "allow" +type_complexity = "allow" diff --git a/crates/bevy_webxr/Cargo.toml b/crates/bevy_webxr/Cargo.toml index 78b671b..7e47cca 100644 --- a/crates/bevy_webxr/Cargo.toml +++ b/crates/bevy_webxr/Cargo.toml @@ -17,3 +17,7 @@ wgpu = "0.19.3" wgpu-hal = "0.19.3" bevy_mod_xr = { path = "../bevy_xr", version = "0.1.0-rc1" } + +[lints.clippy] +too_many_arguments = "allow" +type_complexity = "allow" diff --git a/crates/bevy_xr/Cargo.toml b/crates/bevy_xr/Cargo.toml index e305855..1af524c 100644 --- a/crates/bevy_xr/Cargo.toml +++ b/crates/bevy_xr/Cargo.toml @@ -11,3 +11,7 @@ keywords = ["gamedev", "bevy", "Xr", "Vr"] [dependencies] bevy.workspace = true + +[lints.clippy] +too_many_arguments = "allow" +type_complexity = "allow" diff --git a/crates/bevy_xr/src/hands.rs b/crates/bevy_xr/src/hands.rs index 17a6fd5..7f222ab 100644 --- a/crates/bevy_xr/src/hands.rs +++ b/crates/bevy_xr/src/hands.rs @@ -1,5 +1,4 @@ use bevy::{ - app::Plugin, ecs::{component::Component, entity::Entity, world::Command}, hierarchy::BuildWorldChildren, log::{error, warn}, @@ -8,7 +7,7 @@ use bevy::{ }; use crate::{ - session::{XrSessionCreated, XrTrackingRoot}, + session:: XrTrackingRoot, spaces::XrSpaceLocationFlags, }; pub const HAND_JOINT_COUNT: usize = 26; diff --git a/crates/bevy_xr_utils/Cargo.toml b/crates/bevy_xr_utils/Cargo.toml index 5f66274..ff299fa 100644 --- a/crates/bevy_xr_utils/Cargo.toml +++ b/crates/bevy_xr_utils/Cargo.toml @@ -15,3 +15,7 @@ bevy_mod_openxr = { path = "../bevy_openxr", version = "0.1.0-rc1" } [target.'cfg(not(target_family = "wasm"))'.dependencies] openxr = "0.18.0" + +[lints.clippy] +too_many_arguments = "allow" +type_complexity = "allow" From 66663391349c8b5dcc8ffc81dd7a87d05b94e335 Mon Sep 17 00:00:00 2001 From: Schmarni Date: Mon, 21 Oct 2024 23:32:59 +0200 Subject: [PATCH 3/4] fix ci(hopefully) and fix suboptimal behavior in bevy_xr_utils Signed-off-by: Schmarni --- .github/workflows/ci.yaml | 15 ++++------- crates/bevy_xr_utils/src/lib.rs | 1 - crates/bevy_xr_utils/src/tracking_utils.rs | 14 +++------- crates/bevy_xr_utils/src/xr_utils_actions.rs | 27 ++++++++++++-------- 4 files changed, 25 insertions(+), 32 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 2cb3cb6..d33cdfb 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -24,11 +24,7 @@ jobs: - run: rustup toolchain install stable --profile minimal --no-self-update - - uses: ./ - with: - workspaces: . - - - run: cargo check + - run: cargo check --all --all-targets working-directory: . check_wasm: @@ -43,9 +39,8 @@ jobs: - run: rustup toolchain install stable --profile minimal --target wasm32-unknown-unknown --no-self-update - - uses: ./ - with: - workspaces: . - - - run: cargo check --target wasm32-unknown-unknown + - run: cargo check --target wasm32-unknown-unknown -p bevy_mod_xr + - run: cargo check --target wasm32-unknown-unknown -p bevy_mod_openxr + - run: cargo check --target wasm32-unknown-unknown -p bevy_mod_webxr + - run: cargo check --target wasm32-unknown-unknown -p bevy_mod_xr_utils working-directory: . diff --git a/crates/bevy_xr_utils/src/lib.rs b/crates/bevy_xr_utils/src/lib.rs index 13f8460..ffce3b4 100644 --- a/crates/bevy_xr_utils/src/lib.rs +++ b/crates/bevy_xr_utils/src/lib.rs @@ -1,4 +1,3 @@ -// use bevy::prelude::*; pub mod hand_gizmos; #[cfg(not(target_family = "wasm"))] pub mod tracking_utils; diff --git a/crates/bevy_xr_utils/src/tracking_utils.rs b/crates/bevy_xr_utils/src/tracking_utils.rs index cd75dce..e5a77ed 100644 --- a/crates/bevy_xr_utils/src/tracking_utils.rs +++ b/crates/bevy_xr_utils/src/tracking_utils.rs @@ -1,12 +1,6 @@ use bevy::prelude::*; use bevy_mod_openxr::{ - action_binding::{OxrSendActionBindings, OxrSuggestActionBinding}, - action_set_attaching::OxrAttachActionSet, - action_set_syncing::{OxrActionSetSyncSet, OxrSyncActionSet}, - helper_traits::{ToQuat, ToVec3}, - resources::{OxrFrameState, OxrInstance, Pipelined}, - session::OxrSession, - spaces::{OxrSpaceLocationFlags, OxrSpaceSyncSet}, + action_binding::{OxrSendActionBindings, OxrSuggestActionBinding}, action_set_attaching::OxrAttachActionSet, action_set_syncing::{OxrActionSetSyncSet, OxrSyncActionSet}, helper_traits::{ToQuat, ToVec3}, openxr_session_available, openxr_session_running, resources::{OxrFrameState, OxrInstance, Pipelined}, session::OxrSession, spaces::{OxrSpaceLocationFlags, OxrSpaceSyncSet} }; use bevy_mod_xr::{ session::{session_available, session_running, XrSessionCreated, XrTrackingRoot}, @@ -48,7 +42,7 @@ impl Plugin for TrackingUtilitiesPlugin { PreUpdate, update_head_transforms .in_set(OxrSpaceSyncSet) - .run_if(session_running), + .run_if(openxr_session_running), ); //external app.add_systems(PreUpdate, update_view.after(update_head_transforms)); @@ -66,12 +60,12 @@ impl Plugin for TrackingUtilitiesPlugin { PreUpdate, sync_actions .before(OxrActionSetSyncSet) - .run_if(session_running), + .run_if(openxr_session_running), ); //attach sets app.add_systems(XrSessionCreated, attach_set); //create actions - app.add_systems(Startup, create_actions.run_if(session_available)); + app.add_systems(Startup, create_actions.run_if(openxr_session_available)); app.add_systems(PreUpdate, update_left_grip.after(OxrSpaceSyncSet)); app.add_systems(PreUpdate, update_right_grip.after(OxrSpaceSyncSet)); diff --git a/crates/bevy_xr_utils/src/xr_utils_actions.rs b/crates/bevy_xr_utils/src/xr_utils_actions.rs index 0919567..4a7fc08 100644 --- a/crates/bevy_xr_utils/src/xr_utils_actions.rs +++ b/crates/bevy_xr_utils/src/xr_utils_actions.rs @@ -55,11 +55,13 @@ //! use bevy::prelude::*; use bevy_mod_openxr::{ - action_binding::OxrSuggestActionBinding, action_set_attaching::OxrAttachActionSet, - action_set_syncing::OxrActionSetSyncSet, action_set_syncing::OxrSyncActionSet, - resources::OxrInstance, session::OxrSession, + action_binding::OxrSuggestActionBinding, + action_set_attaching::OxrAttachActionSet, + action_set_syncing::{OxrActionSetSyncSet, OxrSyncActionSet}, + openxr_session_available, openxr_session_running, + resources::OxrInstance, + session::OxrSession, }; -use bevy_mod_xr::session::{session_available, session_running}; use openxr::{Path, Vector2f}; use std::borrow::Cow; @@ -69,37 +71,40 @@ impl Plugin for XRUtilsActionsPlugin { fn build(&self, app: &mut App) { app.configure_sets( Startup, - XRUtilsActionSystemSet::CreateEvents.run_if(session_available), + XRUtilsActionSystemSet::CreateEvents.run_if(openxr_session_available), ); app.configure_sets( PreUpdate, - XRUtilsActionSystemSet::SyncActionStates.run_if(session_running), + XRUtilsActionSystemSet::SyncActionStates.run_if(openxr_session_running), ); app.add_systems( Startup, create_openxr_events .in_set(XRUtilsActionSystemSet::CreateEvents) - .run_if(session_available), + .run_if(openxr_session_available), + ); + app.add_systems( + Update, + sync_active_action_sets.run_if(openxr_session_running), ); - app.add_systems(Update, sync_active_action_sets.run_if(session_running)); app.add_systems( PreUpdate, sync_and_update_action_states_f32 - .run_if(session_running) + .run_if(openxr_session_running) .in_set(XRUtilsActionSystemSet::SyncActionStates) .after(OxrActionSetSyncSet), ); app.add_systems( PreUpdate, sync_and_update_action_states_bool - .run_if(session_running) + .run_if(openxr_session_running) .in_set(XRUtilsActionSystemSet::SyncActionStates) .after(OxrActionSetSyncSet), ); app.add_systems( PreUpdate, sync_and_update_action_states_vector - .run_if(session_running) + .run_if(openxr_session_running) .in_set(XRUtilsActionSystemSet::SyncActionStates) .after(OxrActionSetSyncSet), ); From 33eae2e3b0ec3fcbc5362096cd94f3ee152d6f15 Mon Sep 17 00:00:00 2001 From: Schmarni Date: Tue, 22 Oct 2024 00:08:07 +0200 Subject: [PATCH 4/4] update ci Signed-off-by: Schmarni --- .github/workflows/ci.yaml | 47 ++++++++++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index d33cdfb..af72706 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -7,14 +7,31 @@ on: workflow_dispatch: jobs: - check_native: - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest, windows-latest] - name: Check ${{ matrix.os }} - runs-on: ${{ matrix.os }} + + check_linux: + name: Check Ubuntu + runs-on: ubuntu-latest + + env: + CARGO_TERM_COLOR: always + + steps: + - uses: actions/checkout@v4 + + - name: Install bevy dependencies + run: | + sudo apt-get update && sudo apt-get install -y \ + g++ pkg-config libx11-dev libasound2-dev libudev-dev libopenxr-loader1 libopenxr-dev + + - name: Cache cargo dependencies + uses: Swatinem/rust-cache@v2 + + - name: check + run: cargo check --all --all-targets + check_windows: + name: Check Windows + runs-on: windows-latest env: CARGO_TERM_COLOR: always @@ -22,10 +39,11 @@ jobs: steps: - uses: actions/checkout@v4 - - run: rustup toolchain install stable --profile minimal --no-self-update + - name: Cache cargo dependencies + uses: Swatinem/rust-cache@v2 - - run: cargo check --all --all-targets - working-directory: . + - name: check + run: cargo check --all --all-targets check_wasm: name: Check Wasm @@ -37,10 +55,13 @@ jobs: steps: - uses: actions/checkout@v4 - - run: rustup toolchain install stable --profile minimal --target wasm32-unknown-unknown --no-self-update + - name: Cache cargo dependencies + uses: Swatinem/rust-cache@v2 + + - name: install wasm toolchain + run: rustup toolchain install stable --profile minimal --target wasm32-unknown-unknown --no-self-update - run: cargo check --target wasm32-unknown-unknown -p bevy_mod_xr - run: cargo check --target wasm32-unknown-unknown -p bevy_mod_openxr - run: cargo check --target wasm32-unknown-unknown -p bevy_mod_webxr - - run: cargo check --target wasm32-unknown-unknown -p bevy_mod_xr_utils - working-directory: . + - run: cargo check --target wasm32-unknown-unknown -p bevy_xr_utils