fbx_dom/objects/
camera_switcher.rs1use std::collections::HashMap;
7use std::convert::TryFrom;
8
9use fbxscii::ElementAttribute;
10
11use crate::{OwnedObject, Property, objects::AttrExtractorExt};
12
13use super::{FbxObjectTag, FbxTryFromReason, FbxTypeMismatch, fbx_object_tag};
14
15const CAMERA_ID: &str = "CameraId";
16const CAMERA_NAME: &str = "CameraName";
17const CAMERA_INDEX_NAME: &str = "CameraIndexName";
18
19#[derive(Debug, PartialEq)]
20pub struct CameraSwitcher {
21 object: OwnedObject,
22 pub camera_id: i32,
23 pub camera_name: String,
24 pub camera_index_name: String,
25}
26
27impl CameraSwitcher {
28 pub fn inner(&self) -> &OwnedObject {
29 &self.object
30 }
31
32 pub fn into_inner(self) -> OwnedObject {
33 self.object
34 }
35
36 pub fn properties(&self) -> &HashMap<String, Property> {
38 &self.object.properties
39 }
40
41 pub fn property(&self, name: &str) -> Option<&Property> {
42 self.object.properties.get(name)
43 }
44}
45
46fn parse_camera_switcher_fields(
47 attrs: &HashMap<String, ElementAttribute>,
48) -> Result<(i32, String, String), FbxTryFromReason> {
49 let id_tok = attrs.require_token(&CAMERA_ID)?;
50 let camera_id =
51 id_tok
52 .parse::<i32>()
53 .map_err(|e| FbxTryFromReason::InvalidAttributeFormat {
54 name: CAMERA_ID.to_string(),
55 detail: e.to_string(),
56 })?;
57
58 let camera_name = attrs.require_token(&CAMERA_NAME)?.to_string();
59 let camera_index_name = attrs.require_token(&CAMERA_INDEX_NAME)?.to_string();
60
61 Ok((camera_id, camera_name, camera_index_name))
62}
63
64impl TryFrom<OwnedObject> for CameraSwitcher {
65 type Error = FbxTypeMismatch;
66
67 fn try_from(o: OwnedObject) -> Result<Self, Self::Error> {
68 if fbx_object_tag(&o) != FbxObjectTag::CameraSwitcher {
69 return Err(FbxTypeMismatch::wrong_object_kind(
70 o,
71 "CameraSwitcher".to_string(),
72 ));
73 }
74
75 match parse_camera_switcher_fields(&o.attributes) {
76 Ok((camera_id, camera_name, camera_index_name)) => Ok(CameraSwitcher {
77 object: o,
78 camera_id,
79 camera_name,
80 camera_index_name,
81 }),
82 Err(reason) => Err(FbxTypeMismatch { object: o, reason }),
83 }
84 }
85}
86
87#[cfg(test)]
88mod tests {
89 use super::*;
90 use crate::objects::{NODE_ATTRIBUTE_CAMERA_SWITCHER_CLASS_NAME, NODE_ATTRIBUTE_TYPE_NAME};
91 use fbxscii::LeafAttribute;
92 use std::collections::HashMap;
93
94 fn leaf(tokens: &[&str]) -> ElementAttribute {
95 ElementAttribute::Leaf(Box::new(LeafAttribute {
96 key: String::new(),
97 tokens: tokens.iter().map(|s| (*s).to_string()).collect(),
98 }))
99 }
100
101 fn owned_camera_switcher(attrs: HashMap<String, ElementAttribute>) -> OwnedObject {
102 OwnedObject {
103 object_index: 42,
104 name: "Switcher".into(),
105 type_name: NODE_ATTRIBUTE_TYPE_NAME.into(),
106 class_name: NODE_ATTRIBUTE_CAMERA_SWITCHER_CLASS_NAME.into(),
107 properties: HashMap::new(),
108 attributes: attrs,
109 connected_object_ids: vec![],
110 object_property_targets: vec![],
111 pp_property_targets: HashMap::new(),
112 }
113 }
114
115 #[test]
116 fn camera_switcher_try_from_ok() {
117 let mut attrs = HashMap::new();
118 attrs.insert(CAMERA_ID.into(), leaf(&["7"]));
119 attrs.insert(CAMERA_NAME.into(), leaf(&["MainCam"]));
120 attrs.insert(CAMERA_INDEX_NAME.into(), leaf(&["IndexA"]));
121 let o = owned_camera_switcher(attrs);
122 let cs = CameraSwitcher::try_from(o).unwrap();
123 assert_eq!(cs.camera_id, 7);
124 assert_eq!(cs.camera_name, "MainCam");
125 assert_eq!(cs.camera_index_name, "IndexA");
126 }
127
128 #[test]
129 fn camera_switcher_missing_attr() {
130 let mut attrs = HashMap::new();
131 attrs.insert(CAMERA_ID.into(), leaf(&["1"]));
132 attrs.insert(CAMERA_NAME.into(), leaf(&["X"]));
133 let o = owned_camera_switcher(attrs);
134 let err = CameraSwitcher::try_from(o).unwrap_err();
135 assert!(matches!(
136 err.reason,
137 FbxTryFromReason::MissingAttribute {
138 name: ref n,
139 }
140 if n == CAMERA_INDEX_NAME
141 ));
142 }
143
144 #[test]
145 fn camera_switcher_wrong_kind() {
146 let o = OwnedObject {
147 object_index: 1,
148 name: "g".into(),
149 type_name: "Geometry".into(),
150 class_name: "Mesh".into(),
151 properties: HashMap::new(),
152 attributes: HashMap::new(),
153 connected_object_ids: vec![],
154 object_property_targets: vec![],
155 pp_property_targets: HashMap::new(),
156 };
157 let err = CameraSwitcher::try_from(o).unwrap_err();
158 assert!(matches!(
159 err.reason,
160 FbxTryFromReason::WrongObjectKind { expected: ref e, ..}
161 if e == "CameraSwitcher"
162 ));
163 }
164
165 #[test]
166 fn property_accessors_return_owned_object_properties() {
167 let mut attrs = HashMap::new();
168 attrs.insert(CAMERA_ID.into(), leaf(&["7"]));
169 attrs.insert(CAMERA_NAME.into(), leaf(&["MainCam"]));
170 attrs.insert(CAMERA_INDEX_NAME.into(), leaf(&["IndexA"]));
171
172 let mut o = owned_camera_switcher(attrs);
173 o.properties
174 .insert("SomeFlag".to_string(), Property::Bool(true));
175
176 let cs = CameraSwitcher::try_from(o).unwrap();
177 assert_eq!(cs.property("SomeFlag"), Some(&Property::Bool(true)));
178 assert_eq!(cs.properties().len(), 1);
179 }
180}