move spawn_hand_bones from openxr to xr and add spawn handtracker command
Signed-off-by: Schmarni <marnistromer@gmail.com>
This commit is contained in:
@@ -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<T: Bundle>(
|
||||
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<B: Bundle> {
|
||||
pub joints: XrHandBoneEntities,
|
||||
pub tracker_bundle: B,
|
||||
pub side: HandSide,
|
||||
}
|
||||
|
||||
impl<B: Bundle> Command for SpawnHandTracker<B> {
|
||||
fn apply(self, world: &mut bevy::prelude::World) {
|
||||
let Some(executor) = world.remove_resource::<SpawnHandTrackerCommandExecutor>() else {
|
||||
warn!("no SpawnHandTracker executor defined, skipping handtracker creation");
|
||||
return;
|
||||
};
|
||||
let Ok(root) = world
|
||||
.query_filtered::<Entity, With<XrTrackingRoot>>()
|
||||
.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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user