aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/webxr/xrhand.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/dom/webxr/xrhand.rs')
-rw-r--r--components/script/dom/webxr/xrhand.rs176
1 files changed, 176 insertions, 0 deletions
diff --git a/components/script/dom/webxr/xrhand.rs b/components/script/dom/webxr/xrhand.rs
new file mode 100644
index 00000000000..b73e9cddb35
--- /dev/null
+++ b/components/script/dom/webxr/xrhand.rs
@@ -0,0 +1,176 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+
+use dom_struct::dom_struct;
+use webxr_api::{FingerJoint, Hand, Joint};
+
+use crate::dom::bindings::codegen::Bindings::XRHandBinding::{XRHandJoint, XRHandMethods};
+use crate::dom::bindings::iterable::Iterable;
+use crate::dom::bindings::reflector::{reflect_dom_object, Reflector};
+use crate::dom::bindings::root::{Dom, DomRoot};
+use crate::dom::globalscope::GlobalScope;
+use crate::dom::xrinputsource::XRInputSource;
+use crate::dom::xrjointspace::XRJointSpace;
+
+const JOINT_SPACE_MAP: [(XRHandJoint, Joint); 25] = [
+ (XRHandJoint::Wrist, Joint::Wrist),
+ (XRHandJoint::Thumb_metacarpal, Joint::ThumbMetacarpal),
+ (
+ XRHandJoint::Thumb_phalanx_proximal,
+ Joint::ThumbPhalanxProximal,
+ ),
+ (XRHandJoint::Thumb_phalanx_distal, Joint::ThumbPhalanxDistal),
+ (XRHandJoint::Thumb_tip, Joint::ThumbPhalanxTip),
+ (
+ XRHandJoint::Index_finger_metacarpal,
+ Joint::Index(FingerJoint::Metacarpal),
+ ),
+ (
+ XRHandJoint::Index_finger_phalanx_proximal,
+ Joint::Index(FingerJoint::PhalanxProximal),
+ ),
+ (XRHandJoint::Index_finger_phalanx_intermediate, {
+ Joint::Index(FingerJoint::PhalanxIntermediate)
+ }),
+ (
+ XRHandJoint::Index_finger_phalanx_distal,
+ Joint::Index(FingerJoint::PhalanxDistal),
+ ),
+ (
+ XRHandJoint::Index_finger_tip,
+ Joint::Index(FingerJoint::PhalanxTip),
+ ),
+ (
+ XRHandJoint::Middle_finger_metacarpal,
+ Joint::Middle(FingerJoint::Metacarpal),
+ ),
+ (
+ XRHandJoint::Middle_finger_phalanx_proximal,
+ Joint::Middle(FingerJoint::PhalanxProximal),
+ ),
+ (XRHandJoint::Middle_finger_phalanx_intermediate, {
+ Joint::Middle(FingerJoint::PhalanxIntermediate)
+ }),
+ (
+ XRHandJoint::Middle_finger_phalanx_distal,
+ Joint::Middle(FingerJoint::PhalanxDistal),
+ ),
+ (
+ XRHandJoint::Middle_finger_tip,
+ Joint::Middle(FingerJoint::PhalanxTip),
+ ),
+ (
+ XRHandJoint::Ring_finger_metacarpal,
+ Joint::Ring(FingerJoint::Metacarpal),
+ ),
+ (
+ XRHandJoint::Ring_finger_phalanx_proximal,
+ Joint::Ring(FingerJoint::PhalanxProximal),
+ ),
+ (XRHandJoint::Ring_finger_phalanx_intermediate, {
+ Joint::Ring(FingerJoint::PhalanxIntermediate)
+ }),
+ (
+ XRHandJoint::Ring_finger_phalanx_distal,
+ Joint::Ring(FingerJoint::PhalanxDistal),
+ ),
+ (
+ XRHandJoint::Ring_finger_tip,
+ Joint::Ring(FingerJoint::PhalanxTip),
+ ),
+ (
+ XRHandJoint::Pinky_finger_metacarpal,
+ Joint::Little(FingerJoint::Metacarpal),
+ ),
+ (
+ XRHandJoint::Pinky_finger_phalanx_proximal,
+ Joint::Little(FingerJoint::PhalanxProximal),
+ ),
+ (XRHandJoint::Pinky_finger_phalanx_intermediate, {
+ Joint::Little(FingerJoint::PhalanxIntermediate)
+ }),
+ (
+ XRHandJoint::Pinky_finger_phalanx_distal,
+ Joint::Little(FingerJoint::PhalanxDistal),
+ ),
+ (
+ XRHandJoint::Pinky_finger_tip,
+ Joint::Little(FingerJoint::PhalanxTip),
+ ),
+];
+
+#[dom_struct]
+pub struct XRHand {
+ reflector_: Reflector,
+ #[ignore_malloc_size_of = "defined in webxr"]
+ source: Dom<XRInputSource>,
+ #[ignore_malloc_size_of = "partially defind in webxr"]
+ #[custom_trace]
+ spaces: Hand<Dom<XRJointSpace>>,
+}
+
+impl XRHand {
+ fn new_inherited(source: &XRInputSource, spaces: &Hand<DomRoot<XRJointSpace>>) -> XRHand {
+ XRHand {
+ reflector_: Reflector::new(),
+ source: Dom::from_ref(source),
+ spaces: spaces.map(|j, _| j.as_ref().map(|j| Dom::from_ref(&**j))),
+ }
+ }
+
+ pub fn new(global: &GlobalScope, source: &XRInputSource, support: Hand<()>) -> DomRoot<XRHand> {
+ let id = source.id();
+ let session = source.session();
+ let spaces = support.map(|field, joint| {
+ let hand_joint = JOINT_SPACE_MAP
+ .iter()
+ .find(|&&(_, value)| value == joint)
+ .map(|&(hand_joint, _)| hand_joint)
+ .expect("Invalid joint name");
+ field.map(|_| XRJointSpace::new(global, session, id, joint, hand_joint))
+ });
+ reflect_dom_object(Box::new(XRHand::new_inherited(source, &spaces)), global)
+ }
+}
+
+impl XRHandMethods<crate::DomTypeHolder> for XRHand {
+ /// <https://github.com/immersive-web/webxr-hands-input/blob/master/explainer.md>
+ fn Size(&self) -> u32 {
+ XRHandJoint::Pinky_finger_tip as u32 + 1
+ }
+
+ /// <https://github.com/immersive-web/webxr-hands-input/blob/master/explainer.md>
+ fn Get(&self, joint_name: XRHandJoint) -> DomRoot<XRJointSpace> {
+ let joint = JOINT_SPACE_MAP
+ .iter()
+ .find(|&&(key, _)| key == joint_name)
+ .map(|&(_, joint)| joint)
+ .expect("Invalid joint name");
+ self.spaces
+ .get(joint)
+ .map(|j| DomRoot::from_ref(&**j))
+ .expect("Failed to get joint pose")
+ }
+}
+
+impl Iterable for XRHand {
+ type Key = XRHandJoint;
+ type Value = DomRoot<XRJointSpace>;
+
+ fn get_iterable_length(&self) -> u32 {
+ JOINT_SPACE_MAP.len() as u32
+ }
+
+ fn get_value_at_index(&self, n: u32) -> DomRoot<XRJointSpace> {
+ let joint = JOINT_SPACE_MAP[n as usize].1;
+ self.spaces
+ .get(joint)
+ .map(|j| DomRoot::from_ref(&**j))
+ .expect("Failed to get joint pose")
+ }
+
+ fn get_key_at_index(&self, n: u32) -> XRHandJoint {
+ JOINT_SPACE_MAP[n as usize].0
+ }
+}