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 pub(crate) iter: indexmap::map::Iter<'a, String, gltf_v1_json::Technique>,
42
43 pub(crate) document: &'a Document,
45}
46
47#[derive(Clone, Debug)]
48pub struct Materials<'a> {
49 pub(crate) iter: indexmap::map::Iter<'a, String, gltf_v1_json::Material>,
51
52 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}