blender_armature/action/
bone_keyframes.rs

1use std::collections::HashMap;
2use std::ops::Deref;
3
4use crate::serialize_hashmap_deterministic;
5
6pub use self::bone_keyframe::*;
7pub use self::sorted_keyframes::*;
8
9mod bone_keyframe;
10mod sample;
11mod sorted_keyframes;
12
13/// The keyframes for the transformations for a bone
14///
15/// TODO: Custom deserialize to guarantee that the frame_range_inclusive is correct by checking
16///  against all of the keyframes
17#[derive(Debug, PartialEq, Serialize, Deserialize, Default, Clone)]
18pub struct BoneKeyframes {
19    frame_range_inclusive: Option<(u16, u16)>,
20    #[serde(serialize_with = "serialize_hashmap_deterministic")]
21    keyframes: HashMap<u8, SortedKeyframes>,
22}
23
24impl BoneKeyframes {
25    /// Create an empty set of bone keyframes.
26    pub fn new() -> BoneKeyframes {
27        Self::default()
28    }
29
30    /// Create a new set of bone keyframes
31    #[cfg(test)]
32    pub fn new_with_keyframes(mut keyframes: Vec<BoneKeyframe>) -> Self {
33        use crate::test_util::BONE_IDX;
34        let mut map = HashMap::new();
35        map.insert(BONE_IDX, SortedKeyframes::new(keyframes));
36
37        let mut keyframes = BoneKeyframes {
38            frame_range_inclusive: None,
39            keyframes: map,
40        };
41
42        keyframes.update_frame_range_inclusive();
43
44        keyframes
45    }
46
47    pub fn smallest_frame(&self) -> Option<u16> {
48        Some(self.frame_range_inclusive?.0)
49    }
50
51    pub fn largest_frame(&self) -> Option<u16> {
52        Some(self.frame_range_inclusive?.1)
53    }
54
55    pub fn frame_duration(&self) -> Option<u16> {
56        Some(self.largest_frame()? - self.smallest_frame()?)
57    }
58
59    pub fn frame_range_inclusive(&self) -> Option<(u16, u16)> {
60        self.frame_range_inclusive
61    }
62
63    /// Add a trnasformation keyframe for a bone.
64    pub fn insert_bone_keyframe(&mut self, bone_idx: u8, keyframe: BoneKeyframe) {
65        let keyframes = self.keyframes.entry(bone_idx).or_default();
66
67        keyframes.push(keyframe);
68
69        keyframes.sort_by(|a, b| a.frame().cmp(&b.frame()));
70
71        self.update_frame_range_inclusive();
72    }
73
74    fn update_frame_range_inclusive(&mut self) {
75        let mut frame_range_inclusive = None;
76
77        let mut frames_found = false;
78
79        let mut smallest_frame = u16::max_value();
80        let mut largest_frame = 0;
81
82        for (_, keyframes) in self.keyframes.iter_mut() {
83            for keyframe in keyframes.iter() {
84                frames_found = true;
85
86                smallest_frame = smallest_frame.min(keyframe.frame());
87                largest_frame = largest_frame.max(keyframe.frame());
88            }
89
90            keyframes.sort_by(|a, b| a.frame().cmp(&b.frame()));
91        }
92
93        if frames_found {
94            frame_range_inclusive = Some((smallest_frame, largest_frame));
95        }
96
97        self.frame_range_inclusive = frame_range_inclusive;
98    }
99}
100
101impl Deref for BoneKeyframes {
102    type Target = HashMap<u8, SortedKeyframes>;
103
104    fn deref(&self) -> &Self::Target {
105        &self.keyframes
106    }
107}
108
109impl BoneKeyframes {
110    pub(crate) fn keyframes_mut(&mut self) -> &mut HashMap<u8, SortedKeyframes> {
111        &mut self.keyframes
112    }
113}