blender_armature/action/
bone_keyframes.rs1use 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#[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 pub fn new() -> BoneKeyframes {
27 Self::default()
28 }
29
30 #[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 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}