fbxcel_dom/v7400/data/mesh/
layer.rs

1//! Layers.
2
3use std::convert::{TryFrom, TryInto};
4
5use anyhow::{bail, format_err, Error};
6
7use fbxcel::{low::v7400::AttributeValue, tree::v7400::NodeHandle};
8
9pub(crate) use self::common::LayerContentIndex;
10pub use self::{
11    color::LayerElementColorHandle,
12    common::{LayerElementHandle, MappingMode, ReferenceInformation, ReferenceMode},
13    material::LayerElementMaterialHandle,
14    normal::LayerElementNormalHandle,
15    uv::LayerElementUvHandle,
16};
17
18pub mod color;
19mod common;
20pub mod material;
21pub mod normal;
22pub mod uv;
23
24/// Layer node.
25#[derive(Debug, Clone, Copy)]
26pub struct LayerHandle<'a> {
27    /// `Layer` node under `Geometry`.
28    node: NodeHandle<'a>,
29}
30
31impl<'a> LayerHandle<'a> {
32    /// Creates a new `LayerHandle`.
33    pub(crate) fn new(node: NodeHandle<'a>) -> Self {
34        Self { node }
35    }
36
37    /// Get layer index.
38    pub fn get_index(&self) -> Result<LayerIndex, Error> {
39        let raw = self
40            .node
41            .attributes()
42            .get(0)
43            .ok_or_else(|| format_err!("Attributes not found for `Layer` element"))?
44            .get_i32_or_type()
45            .map_err(|ty| format_err!("Expected `i32` as layer index, but got {:?}", ty))?;
46        if raw < 0 {
47            bail!(
48                "Expected non-negative integer as layer index, but got {:?}",
49                raw
50            );
51        }
52
53        Ok(LayerIndex::new(raw as u32))
54    }
55
56    /// Returns an iterator of layer element entries.
57    pub fn layer_element_entries(&self) -> impl Iterator<Item = LayerElementEntryHandle<'a>> {
58        self.children_by_name("LayerElement")
59            .map(LayerElementEntryHandle::new)
60    }
61}
62
63impl<'a> std::ops::Deref for LayerHandle<'a> {
64    type Target = NodeHandle<'a>;
65
66    fn deref(&self) -> &Self::Target {
67        &self.node
68    }
69}
70
71/// Layer index.
72#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
73pub struct LayerIndex(u32);
74
75impl LayerIndex {
76    /// Creates a new `LayerElement`.
77    fn new(v: u32) -> Self {
78        Self(v)
79    }
80
81    /// Returns the underlying value.
82    pub fn to_u32(self) -> u32 {
83        self.0
84    }
85
86    /// Returns the underlying value.
87    #[deprecated(since = "0.0.3", note = "Renamed to `to_u32`")]
88    pub fn get_u32(self) -> u32 {
89        self.to_u32()
90    }
91}
92
93/// Layer element entry node.
94///
95/// The nodes may be children of a `Layer` element.
96/// They have simple metadata but not layer element content itself.
97#[derive(Debug, Clone, Copy)]
98pub struct LayerElementEntryHandle<'a> {
99    /// `LayerElement` node under `Layer`.
100    node: NodeHandle<'a>,
101}
102
103impl<'a> LayerElementEntryHandle<'a> {
104    /// Creates a new `LayerElementEntryHandle` from the given node handle.
105    fn new(node: NodeHandle<'a>) -> Self {
106        Self { node }
107    }
108
109    /// Returns layer element type string.
110    pub fn type_str(&self) -> Result<&'a str, Error> {
111        self.children_by_name("Type")
112            .next()
113            .ok_or_else(|| format_err!("Child node `Type` not found for `LayerElement`"))?
114            .attributes()
115            .get(0)
116            .ok_or_else(|| format_err!("Attributes not found for `Type`"))?
117            .get_string_or_type()
118            .map_err(|ty| format_err!("Expected string but got {:?}", ty))
119    }
120
121    /// Returns layer element type.
122    pub fn type_(&self) -> Result<LayerElementType, Error> {
123        self.type_str()?.parse()
124    }
125
126    /// Returns the layer element index in the same type.
127    pub fn typed_index(&self) -> Result<LayerElementIndex, Error> {
128        let raw = self
129            .children_by_name("TypedIndex")
130            .next()
131            .ok_or_else(|| format_err!("Child node `TypedIndex` not found for `LayerElement`"))?
132            .attributes()
133            .get(0)
134            .ok_or_else(|| format_err!("Attributes not found for `TypedIndex`"))?
135            .get_i32_or_type()
136            .map_err(|ty| format_err!("Expected `i32` but got {:?}", ty))?;
137        if raw < 0 {
138            bail!(
139                "Expected non-negative integer as layer element index, but got {:?}",
140                raw
141            );
142        }
143
144        Ok(LayerElementIndex::new(raw as u32))
145    }
146
147    /// Returns typed layer element handle.
148    pub fn typed_layer_element(&self) -> Result<TypedLayerElementHandle<'a>, Error> {
149        let geometry_node = self.parent().and_then(|p| p.parent()).ok_or_else(|| {
150            format_err!(
151                "Failed to get parent of parent of `LayerElement` node, \
152                 this is not supposed to happen"
153            )
154        })?;
155        let ty = self.type_()?;
156        let index = self.typed_index()?;
157        geometry_node
158            .children_by_name(ty.type_name())
159            .find(|node| {
160                node.attributes()
161                    .get(0)
162                    .and_then(AttributeValue::get_i32)
163                    .map_or(false, |v| v == index.to_u32() as i32)
164            })
165            .ok_or_else(|| {
166                format_err!(
167                    "Layer element node not found: type={:?}, index={:?}",
168                    ty,
169                    index
170                )
171            })
172            .map(|node| TypedLayerElementHandle::new(ty, node))
173    }
174}
175
176impl<'a> std::ops::Deref for LayerElementEntryHandle<'a> {
177    type Target = NodeHandle<'a>;
178
179    fn deref(&self) -> &Self::Target {
180        &self.node
181    }
182}
183
184/// Layer element type.
185#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
186pub enum LayerElementType {
187    /// Color.
188    Color,
189    /// Material.
190    Material,
191    /// Normal.
192    Normal,
193    /// UV.
194    Uv,
195}
196
197impl LayerElementType {
198    /// Returns type name.
199    pub fn type_name(self) -> &'static str {
200        match self {
201            LayerElementType::Color => "LayerElementColor",
202            LayerElementType::Material => "LayerElementMaterial",
203            LayerElementType::Normal => "LayerElementNormal",
204            LayerElementType::Uv => "LayerElementUV",
205        }
206    }
207}
208
209impl TryFrom<&str> for LayerElementType {
210    type Error = Error;
211
212    fn try_from(s: &str) -> Result<Self, Self::Error> {
213        match s {
214            "LayerElementColor" => Ok(LayerElementType::Color),
215            "LayerElementMaterial" => Ok(LayerElementType::Material),
216            "LayerElementNormal" => Ok(LayerElementType::Normal),
217            "LayerElementUV" => Ok(LayerElementType::Uv),
218            _ => Err(format_err!("Unknown layer element type: {:?}", s)),
219        }
220    }
221}
222
223impl std::str::FromStr for LayerElementType {
224    type Err = Error;
225
226    fn from_str(s: &str) -> Result<Self, Self::Err> {
227        s.try_into()
228    }
229}
230
231/// Type-local layer element index.
232#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
233pub struct LayerElementIndex(u32);
234
235impl LayerElementIndex {
236    /// Creates a new `LayerElementIndex`.
237    fn new(v: u32) -> Self {
238        Self(v)
239    }
240
241    /// Returns the underlying value.
242    pub fn to_u32(self) -> u32 {
243        self.0
244    }
245
246    /// Returns the underlying value.
247    #[deprecated(since = "0.0.3", note = "Renamed to `to_u32`")]
248    pub fn get_u32(self) -> u32 {
249        self.to_u32()
250    }
251}
252
253/// Typed layer element.
254#[derive(Debug, Clone, Copy)]
255pub enum TypedLayerElementHandle<'a> {
256    /// Color.
257    Color(LayerElementColorHandle<'a>),
258    /// Material.
259    Material(LayerElementMaterialHandle<'a>),
260    /// Normal.
261    Normal(LayerElementNormalHandle<'a>),
262    /// UV.
263    Uv(LayerElementUvHandle<'a>),
264}
265
266impl<'a> TypedLayerElementHandle<'a> {
267    /// Creates a new `TypedLayerElementHandle`.
268    fn new(ty: LayerElementType, node: NodeHandle<'a>) -> Self {
269        let base = LayerElementHandle::new(node);
270        match ty {
271            LayerElementType::Color => {
272                TypedLayerElementHandle::Color(LayerElementColorHandle::new(base))
273            }
274            LayerElementType::Material => {
275                TypedLayerElementHandle::Material(LayerElementMaterialHandle::new(base))
276            }
277            LayerElementType::Normal => {
278                TypedLayerElementHandle::Normal(LayerElementNormalHandle::new(base))
279            }
280            LayerElementType::Uv => TypedLayerElementHandle::Uv(LayerElementUvHandle::new(base)),
281        }
282    }
283}
284
285impl<'a> std::ops::Deref for TypedLayerElementHandle<'a> {
286    type Target = LayerElementHandle<'a>;
287
288    fn deref(&self) -> &Self::Target {
289        match self {
290            TypedLayerElementHandle::Color(v) => v,
291            TypedLayerElementHandle::Normal(v) => v,
292            TypedLayerElementHandle::Material(v) => v,
293            TypedLayerElementHandle::Uv(v) => v,
294        }
295    }
296}