Files
server/src/objects/input/sk_hand.rs
2023-09-27 01:16:44 -04:00

106 lines
3.3 KiB
Rust

use crate::{
core::{client::INTERNAL_CLIENT, typed_datamap::TypedDatamap},
nodes::{
input::{hand::Hand, InputMethod, InputType},
spatial::Spatial,
Node,
},
};
use color_eyre::eyre::Result;
use glam::Mat4;
use nanoid::nanoid;
use serde::{Deserialize, Serialize};
use stardust_xr::schemas::flat::{Hand as FlatHand, Joint};
use std::sync::Arc;
use stereokit::{ButtonState, HandJoint, Handed, StereoKitMultiThread};
use tracing::instrument;
fn convert_joint(joint: HandJoint) -> Joint {
Joint {
position: joint.position.into(),
rotation: joint.orientation.into(),
radius: joint.radius,
distance: 0.0,
}
}
#[derive(Default, Deserialize, Serialize)]
struct HandDatamap {
pinch_strength: f32,
grab_strength: f32,
}
pub struct SkHand {
_node: Arc<Node>,
input: Arc<InputMethod>,
handed: Handed,
datamap: TypedDatamap<HandDatamap>,
}
impl SkHand {
pub fn new(handed: Handed) -> Result<Self> {
let _node = Node::create(&INTERNAL_CLIENT, "", &nanoid!(), false).add_to_scenegraph()?;
Spatial::add_to(&_node, None, Mat4::IDENTITY, false)?;
let hand = InputType::Hand(Box::new(Hand {
base: FlatHand {
right: handed == Handed::Right,
..Default::default()
},
}));
let input = InputMethod::add_to(&_node, hand, None)?;
Ok(SkHand {
_node,
input,
handed,
datamap: Default::default(),
})
}
#[instrument(level = "debug", name = "Update Hand Input Method", skip_all)]
pub fn update(&mut self, controller_enabled: bool, sk: &impl StereoKitMultiThread) {
let sk_hand = sk.input_hand(self.handed);
if let InputType::Hand(hand) = &mut *self.input.specialization.lock() {
let controller_active = controller_enabled
&& sk
.input_controller(self.handed)
.tracked
.contains(ButtonState::ACTIVE);
*self.input.enabled.lock() =
!controller_active && sk_hand.tracked_state.contains(ButtonState::ACTIVE);
sk.input_hand_visible(self.handed, *self.input.enabled.lock());
if *self.input.enabled.lock() {
hand.base.thumb.tip = convert_joint(sk_hand.fingers[0][4]);
hand.base.thumb.distal = convert_joint(sk_hand.fingers[0][3]);
hand.base.thumb.proximal = convert_joint(sk_hand.fingers[0][2]);
hand.base.thumb.metacarpal = convert_joint(sk_hand.fingers[0][1]);
for (finger, sk_finger) in [
(&mut hand.base.index, sk_hand.fingers[1]),
(&mut hand.base.middle, sk_hand.fingers[2]),
(&mut hand.base.ring, sk_hand.fingers[3]),
(&mut hand.base.little, sk_hand.fingers[4]),
] {
finger.tip = convert_joint(sk_finger[4]);
finger.distal = convert_joint(sk_finger[3]);
finger.intermediate = convert_joint(sk_finger[2]);
finger.proximal = convert_joint(sk_finger[1]);
finger.metacarpal = convert_joint(sk_finger[0]);
}
hand.base.palm.position = sk_hand.palm.position.into();
hand.base.palm.rotation = sk_hand.palm.orientation.into();
hand.base.palm.radius =
(sk_hand.fingers[2][0].radius + sk_hand.fingers[2][1].radius) * 0.5;
hand.base.wrist.position = sk_hand.wrist.position.into();
hand.base.wrist.rotation = sk_hand.wrist.orientation.into();
hand.base.wrist.radius =
(sk_hand.fingers[0][0].radius + sk_hand.fingers[4][0].radius) * 0.5;
hand.base.elbow = None;
}
}
self.datamap.pinch_strength = sk_hand.pinch_activation;
self.datamap.grab_strength = sk_hand.grip_activation;
*self.input.datamap.lock() = self.datamap.to_datamap().ok();
}
}