fbxcel_dom/v7400/data/mesh/layer/
material.rs1use anyhow::{bail, format_err, Error};
4
5use crate::v7400::data::mesh::{
6 layer::{
7 LayerContentIndex, LayerElementHandle, MappingMode, ReferenceInformation, ReferenceMode,
8 },
9 TriangleVertexIndex, TriangleVertices,
10};
11
12#[derive(Debug, Clone, Copy)]
14pub struct LayerElementMaterialHandle<'a> {
15 node: LayerElementHandle<'a>,
17}
18
19impl<'a> LayerElementMaterialHandle<'a> {
20 pub fn new(node: LayerElementHandle<'a>) -> Self {
22 Self { node }
23 }
24
25 pub fn materials(&self) -> Result<Materials<'a>, Error> {
27 Materials::new(self)
28 }
29
30 fn material_indices_slice(&self) -> Result<&'a [i32], Error> {
32 self.children_by_name("Materials")
33 .next()
34 .ok_or_else(|| format_err!("No `Materials` found for `LayerElementMaterial` node"))?
35 .attributes()
36 .get(0)
37 .ok_or_else(|| format_err!("No attributes found for `Materials` node"))?
38 .get_arr_i32_or_type()
39 .map_err(|ty| format_err!("Expected `[i32]` as material indices, but got {:?}", ty))
40 }
41}
42
43impl<'a> std::ops::Deref for LayerElementMaterialHandle<'a> {
44 type Target = LayerElementHandle<'a>;
45
46 fn deref(&self) -> &Self::Target {
47 &self.node
48 }
49}
50
51#[derive(Debug, Clone, Copy)]
53pub struct Materials<'a> {
54 mapping_mode: MappingMode,
56 indices: &'a [i32],
58}
59
60impl<'a> Materials<'a> {
61 fn new(handle: &LayerElementMaterialHandle<'a>) -> Result<Self, Error> {
63 let mapping_mode = handle.mapping_mode()?;
64 let reference_mode = handle.reference_mode()?;
65 if reference_mode != ReferenceMode::IndexToDirect {
66 bail!(
67 "Unsupported reference mode for material: {:?}",
68 reference_mode
69 );
70 }
71 let indices = handle.material_indices_slice()?;
72
73 Ok(Self {
74 mapping_mode,
75 indices,
76 })
77 }
78
79 pub fn material_index(
81 &self,
82 tris: &TriangleVertices<'a>,
83 tri_vi: TriangleVertexIndex,
84 ) -> Result<MaterialIndex, Error> {
85 let i = LayerContentIndex::control_point_data_from_triangle_vertices(
86 ReferenceInformation::Direct,
87 self.mapping_mode,
88 tris,
89 self.indices.len(),
90 tri_vi,
91 )?;
92 let material_index_index = self.indices[i.get()];
93 if material_index_index < 0 {
94 bail!(
95 "Negative index is not allowed: material_index_index={:?}",
96 material_index_index
97 );
98 }
99
100 Ok(MaterialIndex::new(material_index_index as u32))
101 }
102}
103
104#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
106pub struct MaterialIndex(u32);
107
108impl MaterialIndex {
109 fn new(i: u32) -> Self {
111 Self(i)
112 }
113
114 pub fn to_u32(self) -> u32 {
116 self.0
117 }
118
119 #[deprecated(since = "0.0.3", note = "Renamed to `to_u32`")]
121 pub fn get_u32(self) -> u32 {
122 self.to_u32()
123 }
124}