fbx_dom/objects/
blend_shape.rs1use std::collections::HashMap;
4use std::convert::TryFrom;
5
6use crate::{OwnedDocument, OwnedObject, Property};
7
8use super::{BlendShapeChannel, FbxObjectTag, FbxTypeMismatch, fbx_object_tag};
9
10#[derive(Debug, PartialEq)]
11pub struct BlendShape(pub OwnedObject);
12
13impl BlendShape {
14 pub fn inner(&self) -> &OwnedObject {
15 &self.0
16 }
17
18 pub fn into_inner(self) -> OwnedObject {
19 self.0
20 }
21
22 pub fn properties(&self) -> &HashMap<String, Property> {
23 &self.0.properties
24 }
25
26 pub fn property(&self, name: &str) -> Option<&Property> {
27 self.0.properties.get(name)
28 }
29
30 pub fn get_blend_shape_channels<'a>(
32 &'a self,
33 document: &'a OwnedDocument,
34 ) -> Vec<&'a BlendShapeChannel> {
35 let blend_shape_id = self.inner().object_index;
36 document
37 .blend_shape_channels
38 .iter()
39 .filter(|channel| {
40 channel
41 .inner()
42 .connected_object_ids
43 .contains(&blend_shape_id)
44 })
45 .collect()
46 }
47}
48
49impl TryFrom<OwnedObject> for BlendShape {
50 type Error = FbxTypeMismatch;
51
52 fn try_from(o: OwnedObject) -> Result<Self, Self::Error> {
53 match fbx_object_tag(&o) {
54 FbxObjectTag::BlendShape => Ok(BlendShape(o)),
55 _ => Err(FbxTypeMismatch::wrong_object_kind(
56 o,
57 "BlendShape".to_string(),
58 )),
59 }
60 }
61}
62
63#[cfg(test)]
64mod tests {
65 use std::collections::HashMap;
66 use std::convert::TryFrom;
67
68 use crate::objects::{
69 BlendShapeChannel, DEFORMER_BLEND_SHAPE_CHANNEL_CLASS_NAME,
70 DEFORMER_BLEND_SHAPE_CLASS_NAME, DEFORMER_TYPE_NAME,
71 };
72 use crate::{OwnedDocument, OwnedObject, Property};
73
74 use super::BlendShape;
75
76 #[test]
77 fn property_accessors() {
78 let mut properties = HashMap::new();
79 properties.insert("Foo".into(), Property::Int(7));
80 let o = OwnedObject {
81 object_index: 15,
82 name: "BlendShape::A".into(),
83 type_name: DEFORMER_TYPE_NAME.into(),
84 class_name: DEFORMER_BLEND_SHAPE_CLASS_NAME.into(),
85 properties,
86 attributes: HashMap::new(),
87 connected_object_ids: vec![],
88 object_property_targets: vec![],
89 pp_property_targets: HashMap::new(),
90 };
91 let b = BlendShape::try_from(o).unwrap();
92 assert_eq!(b.property("Foo"), Some(&Property::Int(7)));
93 }
94
95 #[test]
96 fn resolves_blend_shape_channel_connections() {
97 let blend_shape = BlendShape::try_from(OwnedObject {
98 object_index: 50,
99 name: "BlendShape::B".into(),
100 type_name: DEFORMER_TYPE_NAME.into(),
101 class_name: DEFORMER_BLEND_SHAPE_CLASS_NAME.into(),
102 properties: HashMap::new(),
103 attributes: HashMap::new(),
104 connected_object_ids: vec![],
105 object_property_targets: vec![],
106 pp_property_targets: HashMap::new(),
107 })
108 .unwrap();
109 let channel = BlendShapeChannel::try_from(OwnedObject {
110 object_index: 51,
111 name: "BlendShapeChannel::B".into(),
112 type_name: DEFORMER_TYPE_NAME.into(),
113 class_name: DEFORMER_BLEND_SHAPE_CHANNEL_CLASS_NAME.into(),
114 properties: HashMap::new(),
115 attributes: HashMap::new(),
116 connected_object_ids: vec![50],
117 object_property_targets: vec![],
118 pp_property_targets: HashMap::new(),
119 })
120 .unwrap();
121
122 let mut owned = OwnedDocument::default();
123 owned.blend_shape_channels = vec![channel];
124 let linked = blend_shape.get_blend_shape_channels(&owned);
125 assert_eq!(linked.len(), 1);
126 assert_eq!(linked[0].inner().object_index, 51);
127 }
128}