Skip to main content

servo_webxr_api/
hand.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use euclid::RigidTransform3D;
6use malloc_size_of_derive::MallocSizeOf;
7use serde::{Deserialize, Serialize};
8
9use crate::Native;
10
11#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
12pub struct HandSpace;
13
14#[derive(Clone, Debug, Default, Serialize, Deserialize, MallocSizeOf)]
15pub struct Hand<J> {
16    pub wrist: Option<J>,
17    pub thumb_metacarpal: Option<J>,
18    pub thumb_phalanx_proximal: Option<J>,
19    pub thumb_phalanx_distal: Option<J>,
20    pub thumb_phalanx_tip: Option<J>,
21    pub index: Finger<J>,
22    pub middle: Finger<J>,
23    pub ring: Finger<J>,
24    pub little: Finger<J>,
25}
26
27#[derive(Clone, Debug, Default, Serialize, Deserialize, MallocSizeOf)]
28pub struct Finger<J> {
29    pub metacarpal: Option<J>,
30    pub phalanx_proximal: Option<J>,
31    pub phalanx_intermediate: Option<J>,
32    pub phalanx_distal: Option<J>,
33    pub phalanx_tip: Option<J>,
34}
35
36#[derive(Clone, Copy, Debug, Serialize, Deserialize, MallocSizeOf)]
37pub struct JointFrame {
38    pub pose: RigidTransform3D<f32, HandSpace, Native>,
39    pub radius: f32,
40}
41
42impl Default for JointFrame {
43    fn default() -> Self {
44        Self {
45            pose: RigidTransform3D::identity(),
46            radius: 0.,
47        }
48    }
49}
50
51impl<J> Hand<J> {
52    pub fn map<C, R>(
53        &self,
54        cx: &mut C,
55        map: impl (Fn(&mut C, &Option<J>, Joint) -> Option<R>) + Copy,
56    ) -> Hand<R> {
57        Hand {
58            wrist: map(cx, &self.wrist, Joint::Wrist),
59            thumb_metacarpal: map(cx, &self.thumb_metacarpal, Joint::ThumbMetacarpal),
60            thumb_phalanx_proximal: map(
61                cx,
62                &self.thumb_phalanx_proximal,
63                Joint::ThumbPhalanxProximal,
64            ),
65            thumb_phalanx_distal: map(cx, &self.thumb_phalanx_distal, Joint::ThumbPhalanxDistal),
66            thumb_phalanx_tip: map(cx, &self.thumb_phalanx_tip, Joint::ThumbPhalanxTip),
67            index: self.index.map(cx, |cx, f, j| map(cx, f, Joint::Index(j))),
68            middle: self.middle.map(cx, |cx, f, j| map(cx, f, Joint::Middle(j))),
69            ring: self.ring.map(cx, |cx, f, j| map(cx, f, Joint::Ring(j))),
70            little: self.little.map(cx, |cx, f, j| map(cx, f, Joint::Little(j))),
71        }
72    }
73
74    pub fn get(&self, joint: Joint) -> Option<&J> {
75        match joint {
76            Joint::Wrist => self.wrist.as_ref(),
77            Joint::ThumbMetacarpal => self.thumb_metacarpal.as_ref(),
78            Joint::ThumbPhalanxProximal => self.thumb_phalanx_proximal.as_ref(),
79            Joint::ThumbPhalanxDistal => self.thumb_phalanx_distal.as_ref(),
80            Joint::ThumbPhalanxTip => self.thumb_phalanx_tip.as_ref(),
81            Joint::Index(f) => self.index.get(f),
82            Joint::Middle(f) => self.middle.get(f),
83            Joint::Ring(f) => self.ring.get(f),
84            Joint::Little(f) => self.little.get(f),
85        }
86    }
87}
88
89impl<J> Finger<J> {
90    pub fn map<C, R>(
91        &self,
92        cx: &mut C,
93        map: impl (Fn(&mut C, &Option<J>, FingerJoint) -> Option<R>) + Copy,
94    ) -> Finger<R> {
95        Finger {
96            metacarpal: map(cx, &self.metacarpal, FingerJoint::Metacarpal),
97            phalanx_proximal: map(cx, &self.phalanx_proximal, FingerJoint::PhalanxProximal),
98            phalanx_intermediate: map(
99                cx,
100                &self.phalanx_intermediate,
101                FingerJoint::PhalanxIntermediate,
102            ),
103            phalanx_distal: map(cx, &self.phalanx_distal, FingerJoint::PhalanxDistal),
104            phalanx_tip: map(cx, &self.phalanx_tip, FingerJoint::PhalanxTip),
105        }
106    }
107
108    pub fn get(&self, joint: FingerJoint) -> Option<&J> {
109        match joint {
110            FingerJoint::Metacarpal => self.metacarpal.as_ref(),
111            FingerJoint::PhalanxProximal => self.phalanx_proximal.as_ref(),
112            FingerJoint::PhalanxIntermediate => self.phalanx_intermediate.as_ref(),
113            FingerJoint::PhalanxDistal => self.phalanx_distal.as_ref(),
114            FingerJoint::PhalanxTip => self.phalanx_tip.as_ref(),
115        }
116    }
117}
118
119#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
120pub enum FingerJoint {
121    Metacarpal,
122    PhalanxProximal,
123    PhalanxIntermediate,
124    PhalanxDistal,
125    PhalanxTip,
126}
127
128#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
129pub enum Joint {
130    Wrist,
131    ThumbMetacarpal,
132    ThumbPhalanxProximal,
133    ThumbPhalanxDistal,
134    ThumbPhalanxTip,
135    Index(FingerJoint),
136    Middle(FingerJoint),
137    Ring(FingerJoint),
138    Little(FingerJoint),
139}