gltf_v1/
material.rs

1use json::{StringIndex, material::ParameterValue};
2
3use crate::{document::Document, texture::Texture};
4
5#[derive(Clone, Debug)]
6pub enum TexProperty<'a> {
7    Texture(Texture<'a>),
8    Color([f32; 4]),
9}
10
11impl Default for TexProperty<'_> {
12    fn default() -> Self {
13        TexProperty::Color([0.0, 0.0, 0.0, 1.0])
14    }
15}
16
17#[derive(Clone, Debug)]
18pub struct Technique<'a> {
19    #[allow(dead_code)]
20    document: &'a Document,
21
22    index: &'a String,
23
24    json: &'a json::material::Technique,
25}
26
27#[derive(Clone, Debug)]
28pub struct Material<'a> {
29    document: &'a Document,
30
31    index: &'a String,
32
33    json: &'a json::material::Material,
34
35    technique: Technique<'a>,
36}
37
38#[derive(Clone, Debug)]
39pub struct Techniques<'a> {
40    /// Internal accessor iterator.
41    pub(crate) iter: indexmap::map::Iter<'a, String, gltf_v1_json::Technique>,
42
43    /// The internal root glTF object.
44    pub(crate) document: &'a Document,
45}
46
47#[derive(Clone, Debug)]
48pub struct Materials<'a> {
49    /// Internal accessor iterator.
50    pub(crate) iter: indexmap::map::Iter<'a, String, gltf_v1_json::Material>,
51
52    /// The internal root glTF object.
53    pub(crate) document: &'a Document,
54}
55
56impl<'a> Technique<'a> {
57    pub(crate) fn new(
58        document: &'a Document,
59        index: &'a String,
60        json: &'a json::material::Technique,
61    ) -> Self {
62        Self {
63            document,
64            index,
65            json,
66        }
67    }
68    pub fn index(&self) -> &str {
69        self.index
70    }
71    pub fn name(&self) -> Option<&'a str> {
72        self.json.name.as_deref()
73    }
74}
75
76impl<'a> Material<'a> {
77    pub(crate) fn new(
78        document: &'a Document,
79        index: &'a String,
80        json: &'a json::material::Material,
81    ) -> Self {
82        let technique = document
83            .techniques()
84            .find(|x| Some(StringIndex::new(x.index().to_string())) == json.technique)
85            .unwrap();
86
87        Self {
88            document,
89            index,
90            json,
91            technique,
92        }
93    }
94
95    pub fn index(&self) -> &str {
96        self.index
97    }
98    pub fn name(&self) -> Option<&'a str> {
99        self.json.name.as_deref()
100    }
101    pub fn technique(&self) -> &Technique<'a> {
102        &self.technique
103    }
104    pub fn double_sided(&self) -> bool {
105        self.json
106            .values
107            .get("doubleSided")
108            .and_then(|x| match x {
109                json::validation::Checked::Valid(ParameterValue::Boolean(b)) => Some(*b),
110                _ => None,
111            })
112            .unwrap_or(false)
113    }
114    pub fn transparent(&self) -> bool {
115        self.json
116            .values
117            .get("transparent")
118            .and_then(|x| match x {
119                json::validation::Checked::Valid(ParameterValue::Boolean(b)) => Some(*b),
120                _ => None,
121            })
122            .unwrap_or(false)
123    }
124    pub fn transparency(&self) -> f32 {
125        self.json
126            .values
127            .get("transparency")
128            .and_then(|x| match x {
129                json::validation::Checked::Valid(ParameterValue::Number(b)) => Some(*b),
130                _ => None,
131            })
132            .unwrap_or(1.0)
133    }
134    pub fn shininess(&self) -> f32 {
135        self.json
136            .values
137            .get("shininess")
138            .and_then(|x| match x {
139                json::validation::Checked::Valid(ParameterValue::Number(b)) => Some(*b),
140                _ => None,
141            })
142            .unwrap_or(0.0)
143    }
144    pub fn ambient(&self) -> TexProperty<'a> {
145        self.json
146            .values
147            .get("ambient")
148            .and_then(|x| match x {
149                json::validation::Checked::Valid(ParameterValue::NumberArray(b))
150                    if b.len() == 4 =>
151                {
152                    Some(TexProperty::Color([b[0], b[1], b[2], b[3]]))
153                }
154                json::validation::Checked::Valid(ParameterValue::String(str)) => self
155                    .document
156                    .textures()
157                    .find(|x| x.index() == str)
158                    .map(TexProperty::Texture),
159                _ => None,
160            })
161            .unwrap_or_default()
162    }
163    pub fn diffuse(&self) -> TexProperty<'a> {
164        self.json
165            .values
166            .get("diffuse")
167            .and_then(|x| match x {
168                json::validation::Checked::Valid(ParameterValue::NumberArray(b))
169                    if b.len() == 4 =>
170                {
171                    Some(TexProperty::Color([b[0], b[1], b[2], b[3]]))
172                }
173                json::validation::Checked::Valid(ParameterValue::String(str)) => self
174                    .document
175                    .textures()
176                    .find(|x| x.index() == str)
177                    .map(TexProperty::Texture),
178                _ => None,
179            })
180            .unwrap_or_default()
181    }
182    pub fn specular(&self) -> TexProperty<'a> {
183        self.json
184            .values
185            .get("specular")
186            .and_then(|x| match x {
187                json::validation::Checked::Valid(ParameterValue::NumberArray(b))
188                    if b.len() == 4 =>
189                {
190                    Some(TexProperty::Color([b[0], b[1], b[2], b[3]]))
191                }
192                json::validation::Checked::Valid(ParameterValue::String(str)) => self
193                    .document
194                    .textures()
195                    .find(|x| x.index() == str)
196                    .map(TexProperty::Texture),
197                _ => None,
198            })
199            .unwrap_or_default()
200    }
201    pub fn emission(&self) -> TexProperty<'a> {
202        self.json
203            .values
204            .get("emission")
205            .and_then(|x| match x {
206                json::validation::Checked::Valid(ParameterValue::NumberArray(b))
207                    if b.len() == 4 =>
208                {
209                    Some(TexProperty::Color([b[0], b[1], b[2], b[3]]))
210                }
211                json::validation::Checked::Valid(ParameterValue::String(str)) => self
212                    .document
213                    .textures()
214                    .find(|x| x.index() == str)
215                    .map(TexProperty::Texture),
216                _ => None,
217            })
218            .unwrap_or_default()
219    }
220}
221
222impl ExactSizeIterator for Materials<'_> {}
223impl<'a> Iterator for Materials<'a> {
224    type Item = Material<'a>;
225
226    fn next(&mut self) -> Option<Self::Item> {
227        self.iter
228            .next()
229            .map(|(index, json)| Material::new(self.document, index, json))
230    }
231    fn size_hint(&self) -> (usize, Option<usize>) {
232        self.iter.size_hint()
233    }
234    fn count(self) -> usize {
235        self.iter.count()
236    }
237    fn last(self) -> Option<Self::Item> {
238        let document = self.document;
239        self.iter
240            .last()
241            .map(|(index, json)| Material::new(document, index, json))
242    }
243    fn nth(&mut self, n: usize) -> Option<Self::Item> {
244        self.iter
245            .nth(n)
246            .map(|(index, json)| Material::new(self.document, index, json))
247    }
248}
249
250impl ExactSizeIterator for Techniques<'_> {}
251impl<'a> Iterator for Techniques<'a> {
252    type Item = Technique<'a>;
253
254    fn next(&mut self) -> Option<Self::Item> {
255        self.iter
256            .next()
257            .map(|(index, json)| Technique::new(self.document, index, json))
258    }
259    fn size_hint(&self) -> (usize, Option<usize>) {
260        self.iter.size_hint()
261    }
262    fn count(self) -> usize {
263        self.iter.count()
264    }
265    fn last(self) -> Option<Self::Item> {
266        let document = self.document;
267        self.iter
268            .last()
269            .map(|(index, json)| Technique::new(document, index, json))
270    }
271    fn nth(&mut self, n: usize) -> Option<Self::Item> {
272        self.iter
273            .nth(n)
274            .map(|(index, json)| Technique::new(self.document, index, json))
275    }
276}