fbxcel_dom/v7400/data/mesh/layer/
common.rs1use std::convert::{TryFrom, TryInto};
4
5use anyhow::{bail, format_err, Error};
6
7use crate::{
8 fbxcel::tree::v7400::NodeHandle,
9 v7400::data::mesh::{layer::LayerElementIndex, TriangleVertexIndex, TriangleVertices},
10};
11
12#[derive(Debug, Clone, Copy)]
14pub struct LayerElementHandle<'a> {
15 node: NodeHandle<'a>,
17}
18
19impl<'a> LayerElementHandle<'a> {
20 pub(crate) fn new(node: NodeHandle<'a>) -> Self {
22 Self { node }
23 }
24
25 pub fn node(&self) -> &NodeHandle<'a> {
27 &self.node
28 }
29
30 pub fn typed_index(&self) -> Result<LayerElementIndex, Error> {
32 let raw = self
33 .node()
34 .attributes()
35 .get(0)
36 .ok_or_else(|| format_err!("No attributes found for `{}` node", self.node().name()))?
37 .get_i32_or_type()
38 .map_err(|ty| format_err!("Expected `i32` as layer element index, but got {:?}", ty))?;
39 if raw < 0 {
40 bail!(
41 "Expected non-negative integer as layer element index, but got {:?}",
42 raw
43 );
44 }
45
46 Ok(LayerElementIndex::new(raw as u32))
47 }
48
49 pub fn name(&self) -> Result<&'a str, Error> {
55 self.children_by_name("Name")
56 .next()
57 .ok_or_else(|| {
58 format_err!(
59 "Child node `Name` not found for `{}` node",
60 self.node().name()
61 )
62 })?
63 .attributes()
64 .get(0)
65 .ok_or_else(|| format_err!("No attributes found for `{}` node", self.node().name()))?
66 .get_string_or_type()
67 .map_err(|ty| format_err!("Expected string as layer element name, but got {:?}", ty))
68 }
69
70 pub fn mapping_mode(&self) -> Result<MappingMode, Error> {
72 self.children_by_name("MappingInformationType")
73 .next()
74 .ok_or_else(|| {
75 format_err!(
76 "Child node `MappingInformationType` not found for `{}` node",
77 self.node().name()
78 )
79 })?
80 .attributes()
81 .get(0)
82 .ok_or_else(|| format_err!("No attributes found for `{}` node", self.node().name()))?
83 .get_string_or_type()
84 .map_err(|ty| format_err!("Expected string as layer element name, but got {:?}", ty))
85 .and_then(str::parse)
86 }
87
88 pub fn reference_mode(&self) -> Result<ReferenceMode, Error> {
90 self.children_by_name("ReferenceInformationType")
91 .next()
92 .ok_or_else(|| {
93 format_err!(
94 "Child node `ReferenceInformationType` not found for `{}` node",
95 self.node().name()
96 )
97 })?
98 .attributes()
99 .get(0)
100 .ok_or_else(|| format_err!("No attributes found for `{}` node", self.node().name()))?
101 .get_string_or_type()
102 .map_err(|ty| format_err!("Expected string as layer element name, but got {:?}", ty))
103 .and_then(str::parse)
104 }
105}
106
107impl<'a> std::ops::Deref for LayerElementHandle<'a> {
108 type Target = NodeHandle<'a>;
109
110 fn deref(&self) -> &Self::Target {
111 &self.node
112 }
113}
114
115#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
117pub enum MappingMode {
118 None,
120 ByControlPoint,
122 ByPolygonVertex,
124 ByPolygon,
126 ByEdge,
128 AllSame,
130}
131
132impl TryFrom<&str> for MappingMode {
133 type Error = Error;
134
135 fn try_from(s: &str) -> Result<Self, Self::Error> {
136 match s {
137 "ByControlPoint" | "ByVertex" | "ByVertice" => Ok(MappingMode::ByControlPoint),
138 "ByPolygonVertex" => Ok(MappingMode::ByPolygonVertex),
139 "ByPolygon" => Ok(MappingMode::ByPolygon),
140 "ByEdge" => Ok(MappingMode::ByEdge),
141 "AllSame" => Ok(MappingMode::AllSame),
142 s => Err(format_err!("Failed to parse mapping mode: got {:?}", s)),
143 }
144 }
145}
146
147impl std::str::FromStr for MappingMode {
148 type Err = Error;
149
150 fn from_str(s: &str) -> Result<Self, Self::Err> {
151 s.try_into()
152 }
153}
154
155#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
157pub enum ReferenceMode {
158 Direct,
160 IndexToDirect,
162}
163
164impl TryFrom<&str> for ReferenceMode {
165 type Error = Error;
166
167 fn try_from(s: &str) -> Result<Self, Self::Error> {
168 match s {
169 "Direct" => Ok(ReferenceMode::Direct),
170 "IndexToDirect" => Ok(ReferenceMode::IndexToDirect),
171 s => Err(format_err!("Failed to parse reference mode: got {:?}", s)),
172 }
173 }
174}
175
176impl std::str::FromStr for ReferenceMode {
177 type Err = Error;
178
179 fn from_str(s: &str) -> Result<Self, Self::Err> {
180 s.try_into()
181 }
182}
183
184#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
186pub enum ReferenceInformation<'a> {
187 Direct,
189 IndexToDirect(&'a [i32]),
191}
192
193impl ReferenceInformation<'_> {
194 pub(crate) fn get_direct(&self, i: usize) -> Result<LayerContentIndex, Error> {
196 match self {
197 ReferenceInformation::Direct => Ok(LayerContentIndex::new(i)),
198 ReferenceInformation::IndexToDirect(indices) => {
199 let direct = indices.get(i).cloned().ok_or_else(|| {
200 format_err!(
201 "Index out of range: indices.len()={:?}, i={:?}",
202 indices.len(),
203 i
204 )
205 })?;
206 let direct = if direct < 0 {
207 !direct as usize
210 } else {
211 direct as usize
212 };
213 Ok(LayerContentIndex::new(direct))
214 }
215 }
216 }
217}
218
219impl From<ReferenceInformation<'_>> for ReferenceMode {
220 fn from(v: ReferenceInformation<'_>) -> Self {
221 match v {
222 ReferenceInformation::Direct => ReferenceMode::Direct,
223 ReferenceInformation::IndexToDirect(_) => ReferenceMode::IndexToDirect,
224 }
225 }
226}
227
228#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
230pub(crate) struct LayerContentIndex(usize);
231
232impl LayerContentIndex {
233 pub(crate) fn new(i: usize) -> Self {
235 Self(i)
236 }
237
238 pub(crate) fn get(self) -> usize {
240 self.0
241 }
242
243 pub(crate) fn control_point_data_from_triangle_vertices(
245 reference_info: ReferenceInformation<'_>,
246 mapping_mode: MappingMode,
247 triangle_vertices: &TriangleVertices<'_>,
248 layer_element_array_len: usize,
249 tri_vi: TriangleVertexIndex,
250 ) -> Result<LayerContentIndex, Error> {
251 let index = match mapping_mode {
252 MappingMode::None | MappingMode::ByEdge => {
253 bail!("Unsupported mapping mode: {:?}", mapping_mode)
254 }
255 MappingMode::ByControlPoint => {
256 let cpi = triangle_vertices
257 .control_point_index(tri_vi)
258 .ok_or_else(|| {
259 format_err!("Failed to get control point index: tri_vi={:?}", tri_vi)
260 })?;
261 reference_info.get_direct(cpi.to_u32() as usize)?
262 }
263 MappingMode::ByPolygonVertex => {
264 let pvi = triangle_vertices
265 .polygon_vertex_index(tri_vi)
266 .ok_or_else(|| {
267 format_err!("Failed to get polygon vertex index: tri_vi={:?}", tri_vi)
268 })?;
269 reference_info.get_direct(pvi.to_usize())?
270 }
271 MappingMode::ByPolygon => {
272 let poly_i = triangle_vertices
273 .polygon_index(tri_vi.triangle_index())
274 .ok_or_else(|| {
275 format_err!("Failed to get polygon vertex index: tri_vi={:?}", tri_vi)
276 })?;
277 reference_info.get_direct(poly_i.to_usize())?
278 }
279 MappingMode::AllSame => reference_info.get_direct(0)?,
280 };
281 if index.get() >= layer_element_array_len {
282 bail!(
283 "Calculated index out of range: index={:?}, array_len={:?}",
284 index,
285 layer_element_array_len
286 );
287 }
288
289 Ok(index)
290 }
291}