use euclid::RigidTransform3D;
use malloc_size_of_derive::MallocSizeOf;
use serde::{Deserialize, Serialize};
use crate::Native;
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
pub struct HandSpace;
#[derive(Clone, Debug, Default, Serialize, Deserialize, MallocSizeOf)]
pub struct Hand<J> {
pub wrist: Option<J>,
pub thumb_metacarpal: Option<J>,
pub thumb_phalanx_proximal: Option<J>,
pub thumb_phalanx_distal: Option<J>,
pub thumb_phalanx_tip: Option<J>,
pub index: Finger<J>,
pub middle: Finger<J>,
pub ring: Finger<J>,
pub little: Finger<J>,
}
#[derive(Clone, Debug, Default, Serialize, Deserialize, MallocSizeOf)]
pub struct Finger<J> {
pub metacarpal: Option<J>,
pub phalanx_proximal: Option<J>,
pub phalanx_intermediate: Option<J>,
pub phalanx_distal: Option<J>,
pub phalanx_tip: Option<J>,
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize, MallocSizeOf)]
pub struct JointFrame {
pub pose: RigidTransform3D<f32, HandSpace, Native>,
pub radius: f32,
}
impl Default for JointFrame {
fn default() -> Self {
Self {
pose: RigidTransform3D::identity(),
radius: 0.,
}
}
}
impl<J> Hand<J> {
pub fn map<C, R>(
&self,
cx: &mut C,
map: impl (Fn(&mut C, &Option<J>, Joint) -> Option<R>) + Copy,
) -> Hand<R> {
Hand {
wrist: map(cx, &self.wrist, Joint::Wrist),
thumb_metacarpal: map(cx, &self.thumb_metacarpal, Joint::ThumbMetacarpal),
thumb_phalanx_proximal: map(
cx,
&self.thumb_phalanx_proximal,
Joint::ThumbPhalanxProximal,
),
thumb_phalanx_distal: map(cx, &self.thumb_phalanx_distal, Joint::ThumbPhalanxDistal),
thumb_phalanx_tip: map(cx, &self.thumb_phalanx_tip, Joint::ThumbPhalanxTip),
index: self.index.map(cx, |cx, f, j| map(cx, f, Joint::Index(j))),
middle: self.middle.map(cx, |cx, f, j| map(cx, f, Joint::Middle(j))),
ring: self.ring.map(cx, |cx, f, j| map(cx, f, Joint::Ring(j))),
little: self.little.map(cx, |cx, f, j| map(cx, f, Joint::Little(j))),
}
}
pub fn get(&self, joint: Joint) -> Option<&J> {
match joint {
Joint::Wrist => self.wrist.as_ref(),
Joint::ThumbMetacarpal => self.thumb_metacarpal.as_ref(),
Joint::ThumbPhalanxProximal => self.thumb_phalanx_proximal.as_ref(),
Joint::ThumbPhalanxDistal => self.thumb_phalanx_distal.as_ref(),
Joint::ThumbPhalanxTip => self.thumb_phalanx_tip.as_ref(),
Joint::Index(f) => self.index.get(f),
Joint::Middle(f) => self.middle.get(f),
Joint::Ring(f) => self.ring.get(f),
Joint::Little(f) => self.little.get(f),
}
}
}
impl<J> Finger<J> {
pub fn map<C, R>(
&self,
cx: &mut C,
map: impl (Fn(&mut C, &Option<J>, FingerJoint) -> Option<R>) + Copy,
) -> Finger<R> {
Finger {
metacarpal: map(cx, &self.metacarpal, FingerJoint::Metacarpal),
phalanx_proximal: map(cx, &self.phalanx_proximal, FingerJoint::PhalanxProximal),
phalanx_intermediate: map(
cx,
&self.phalanx_intermediate,
FingerJoint::PhalanxIntermediate,
),
phalanx_distal: map(cx, &self.phalanx_distal, FingerJoint::PhalanxDistal),
phalanx_tip: map(cx, &self.phalanx_tip, FingerJoint::PhalanxTip),
}
}
pub fn get(&self, joint: FingerJoint) -> Option<&J> {
match joint {
FingerJoint::Metacarpal => self.metacarpal.as_ref(),
FingerJoint::PhalanxProximal => self.phalanx_proximal.as_ref(),
FingerJoint::PhalanxIntermediate => self.phalanx_intermediate.as_ref(),
FingerJoint::PhalanxDistal => self.phalanx_distal.as_ref(),
FingerJoint::PhalanxTip => self.phalanx_tip.as_ref(),
}
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub enum FingerJoint {
Metacarpal,
PhalanxProximal,
PhalanxIntermediate,
PhalanxDistal,
PhalanxTip,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub enum Joint {
Wrist,
ThumbMetacarpal,
ThumbPhalanxProximal,
ThumbPhalanxDistal,
ThumbPhalanxTip,
Index(FingerJoint),
Middle(FingerJoint),
Ring(FingerJoint),
Little(FingerJoint),
}