1use std::result::Result;
2
3use crate::{
4 get_on_off_from_str, get_opt_token_float_opt, get_token_float, get_token_int, get_token_string,
5 tokenizer::{Token, TokenSet},
6};
7use nom::{
8 branch::alt,
9 combinator::{map, opt},
10 error,
11 multi::many1,
12 sequence::preceded,
13 IResult, Parser,
14};
15use thiserror::Error;
16
17#[derive(Debug, Clone, PartialEq)]
19pub enum ColorType {
20 Rgb(f32, f32, f32),
22 Spectral(String, f32),
25 CieXyz(f32, f32, f32),
27}
28
29#[derive(Debug, Clone, Copy, PartialEq)]
31pub enum DisolveType {
32 Alpha(f32),
35 Halo(f32),
38}
39
40#[derive(Clone, Debug)]
41enum OptionElement {
42 FileName(String),
43 BlendU(bool),
44 BlendV(bool),
45 Cc(bool),
46 Clamp(bool),
47 TextureRange((f32, f32)),
48 Offset((f32, Option<f32>, Option<f32>)),
49 Scale((f32, Option<f32>, Option<f32>)),
50 Turbulance((f32, Option<f32>, Option<f32>)),
51 TextureRes(i32),
52 ImfChan(String),
53 BumpMultiplier(f32),
54 ReflectionType(String),
55}
56
57#[derive(Debug, Default, Clone, PartialEq)]
59pub struct ColorCorrectedMap {
60 pub file_name: String,
62 pub blend_u: Option<bool>,
64 pub blend_v: Option<bool>,
66 pub color_correct: Option<bool>,
68 pub clamp: Option<bool>,
70 pub texture_range: Option<(f32, f32)>,
73 pub offset: Option<(f32, Option<f32>, Option<f32>)>,
75 pub scale: Option<(f32, Option<f32>, Option<f32>)>,
77 pub turbulance: Option<(f32, Option<f32>, Option<f32>)>,
79 pub texture_res: Option<i32>,
82}
83
84impl ColorCorrectedMap {
85 fn new(o: &[OptionElement]) -> Self {
86 let mut res = Self::default();
87 for e in o {
88 match e {
89 OptionElement::FileName(n) => res.file_name = n.clone(),
90 OptionElement::BlendU(b) => {
91 res.blend_u = Some(*b);
92 },
93 OptionElement::BlendV(b) => {
94 res.blend_v = Some(*b);
95 },
96 OptionElement::Cc(b) => {
97 res.color_correct = Some(*b);
98 },
99 OptionElement::Clamp(b) => {
100 res.clamp = Some(*b);
101 },
102 OptionElement::TextureRange((base, gain)) => {
103 res.texture_range = Some((*base, *gain));
104 },
105 OptionElement::Offset((x, y, z)) => {
106 res.offset = Some((*x, *y, *z));
107 },
108 OptionElement::Scale((x, y, z)) => {
109 res.scale = Some((*x, *y, *z));
110 },
111 OptionElement::Turbulance((x, y, z)) => {
112 res.turbulance = Some((*x, *y, *z));
113 },
114 OptionElement::TextureRes(tex_res) => {
115 res.texture_res = Some(*tex_res);
116 },
117 _ => {},
118 }
119 }
120 res
121 }
122}
123
124#[derive(Debug, Default, Clone, PartialEq)]
126pub struct NonColorCorrectedMap {
127 pub file_name: String,
129 pub blend_u: Option<bool>,
131 pub blend_v: Option<bool>,
133 pub clamp: Option<bool>,
135 pub imf_chan: Option<String>,
138 pub texture_range: Option<(f32, f32)>,
141 pub offset: Option<(f32, Option<f32>, Option<f32>)>,
143 pub scale: Option<(f32, Option<f32>, Option<f32>)>,
145 pub turbulance: Option<(f32, Option<f32>, Option<f32>)>,
147 pub texture_res: Option<i32>,
150}
151
152impl NonColorCorrectedMap {
153 fn new(o: &[OptionElement]) -> Self {
154 let mut res = Self::default();
155 for e in o {
156 match e {
157 OptionElement::FileName(n) => res.file_name = n.clone(),
158 OptionElement::BlendU(b) => {
159 res.blend_u = Some(*b);
160 },
161 OptionElement::BlendV(b) => {
162 res.blend_v = Some(*b);
163 },
164 OptionElement::Clamp(b) => {
165 res.clamp = Some(*b);
166 },
167 OptionElement::ImfChan(chan) => res.imf_chan = Some(chan.clone()),
168 OptionElement::TextureRange((base, gain)) => {
169 res.texture_range = Some((*base, *gain));
170 },
171 OptionElement::Offset((x, y, z)) => {
172 res.offset = Some((*x, *y, *z));
173 },
174 OptionElement::Scale((x, y, z)) => {
175 res.scale = Some((*x, *y, *z));
176 },
177 OptionElement::Turbulance((x, y, z)) => {
178 res.turbulance = Some((*x, *y, *z));
179 },
180 OptionElement::TextureRes(tex_res) => {
181 res.texture_res = Some(*tex_res);
182 },
183 _ => {},
184 }
185 }
186 res
187 }
188}
189
190#[derive(Debug, Default, Clone, PartialEq)]
192pub struct BumpMap {
193 pub bump_multiplier: Option<f32>,
195 pub map_settings: Option<NonColorCorrectedMap>,
197}
198
199impl BumpMap {
200 fn new(o: &[OptionElement]) -> Self {
201 let mut res = Self {
202 map_settings: Some(NonColorCorrectedMap::new(o)),
203 ..Default::default()
204 };
205
206 for e in o {
207 if let OptionElement::BumpMultiplier(bm) = e {
208 res.bump_multiplier = Some(*bm);
209 break;
210 }
211 }
212 res
213 }
214}
215
216#[derive(Debug, Default, Clone, PartialEq)]
218pub struct ReflectionMap {
219 pub reflection_type: String,
222 pub map_settings: Option<ColorCorrectedMap>,
224}
225
226impl ReflectionMap {
227 fn new(o: &[OptionElement]) -> Self {
228 let mut res = Self {
229 map_settings: Some(ColorCorrectedMap::new(o)),
230 ..Default::default()
231 };
232
233 for e in o {
234 if let OptionElement::ReflectionType(ty) = e {
235 res.reflection_type = ty.clone();
236 break;
237 }
238 }
239 res
240 }
241}
242
243#[derive(Debug, Default, Clone, PartialEq)]
245pub struct Material {
246 pub name: String,
249 pub ambient: Option<ColorType>,
252 pub diffuse: Option<ColorType>,
255 pub specular: Option<ColorType>,
258 pub emissive_coefficient: Option<ColorType>,
261 pub specular_exponent: Option<f32>,
264 pub disolve: Option<DisolveType>,
267 pub transparancy: Option<f32>,
270 pub transmission_factor: Option<ColorType>,
273 pub sharpness: Option<f32>,
275 pub index_of_refraction: Option<f32>,
277 pub illumination_mode: Option<u32>,
279 pub texture_map_ambient: Option<ColorCorrectedMap>,
281 pub texture_map_diffuse: Option<ColorCorrectedMap>,
283 pub texture_map_specular: Option<ColorCorrectedMap>,
285 pub shininess_map: Option<NonColorCorrectedMap>,
287 pub disolve_map: Option<NonColorCorrectedMap>,
289 pub displacement_map: Option<NonColorCorrectedMap>,
291 pub decal: Option<NonColorCorrectedMap>,
293 pub bump_map: Option<BumpMap>,
295 pub reflection_map: Option<ReflectionMap>,
297 pub anti_alias_map: Option<bool>,
300}
301
302impl Material {
303 fn set_from_material_element(&mut self, element: &MaterialElement) {
304 match element {
305 MaterialElement::Name(n) => {
306 self.name = n.clone();
307 },
308 MaterialElement::Ambient(c) => {
309 self.ambient = Some(c.clone());
310 },
311 MaterialElement::Diffuse(c) => {
312 self.diffuse = Some(c.clone());
313 },
314 MaterialElement::Specular(c) => {
315 self.specular = Some(c.clone());
316 },
317 MaterialElement::EmissiveCoefficient(c) => {
318 self.emissive_coefficient = Some(c.clone());
319 },
320 MaterialElement::SpecularExponent(f) => {
321 self.specular_exponent = Some(*f);
322 },
323 MaterialElement::Disolve(d) => {
324 self.disolve = Some(*d);
325 },
326 MaterialElement::Transparency(f) => {
327 self.transparancy = Some(*f);
328 },
329 MaterialElement::TransmissionFactor(c) => {
330 self.transmission_factor = Some(c.clone());
331 },
332 MaterialElement::Sharpness(f) => {
333 self.sharpness = Some(*f);
334 },
335 MaterialElement::IndexOfRefraction(f) => {
336 self.index_of_refraction = Some(*f);
337 },
338 MaterialElement::IlluminationModel(u) => {
339 self.illumination_mode = Some(*u);
340 },
341 MaterialElement::TexMapAmbient(cc) => {
342 self.texture_map_ambient = Some(cc.clone());
343 },
344 MaterialElement::TexMapDiffuse(cc) => {
345 self.texture_map_diffuse = Some(cc.clone());
346 },
347 MaterialElement::TexMapSpecular(cc) => {
348 self.texture_map_specular = Some(cc.clone());
349 },
350 MaterialElement::ShininessMap(ncc) => {
351 self.shininess_map = Some(ncc.clone());
352 },
353 MaterialElement::DisolveMap(ncc) => {
354 self.disolve_map = Some(ncc.clone());
355 },
356 MaterialElement::DisplacementMap(ncc) => {
357 self.displacement_map = Some(ncc.clone());
358 },
359 MaterialElement::Decal(ncc) => {
360 self.decal = Some(ncc.clone());
361 },
362 MaterialElement::BumpMap(bm) => {
363 self.bump_map = Some(bm.clone());
364 },
365 MaterialElement::ReflectionMap(rm) => {
366 self.reflection_map = Some(rm.clone());
367 },
368 MaterialElement::AntiAliasMap(b) => {
369 self.anti_alias_map = Some(*b);
370 },
371 }
372 }
373}
374
375#[derive(Error, Debug)]
378pub enum MaterialError {
379 #[error("Parse Error: `{0}`")]
380 Parse(String),
381
382 #[error("New Material expected, but not found.")]
386 NewMaterial,
387}
388
389#[derive(Clone, Debug)]
390enum MaterialElement {
391 Name(String),
392 Ambient(ColorType),
393 Diffuse(ColorType),
394 Specular(ColorType),
395 EmissiveCoefficient(ColorType),
396 SpecularExponent(f32),
397 Disolve(DisolveType),
398 Transparency(f32),
399 TransmissionFactor(ColorType),
400 Sharpness(f32),
401 IndexOfRefraction(f32),
402 IlluminationModel(u32),
403 TexMapAmbient(ColorCorrectedMap),
404 TexMapDiffuse(ColorCorrectedMap),
405 TexMapSpecular(ColorCorrectedMap),
406 ShininessMap(NonColorCorrectedMap),
407 DisolveMap(NonColorCorrectedMap),
408 DisplacementMap(NonColorCorrectedMap),
409 Decal(NonColorCorrectedMap),
410 BumpMap(BumpMap),
411 ReflectionMap(ReflectionMap),
412 AntiAliasMap(bool),
413}
414
415pub(crate) fn parse(input: TokenSet<'_>) -> Result<Vec<Material>, MaterialError> {
416 let elements: Vec<MaterialElement> = match parse_material_set().parse_complete(input) {
417 Ok((_, x)) => x,
418 Err(e) => return Err(MaterialError::Parse(e.to_string())),
419 };
420
421 let mut res = Vec::new();
422 for e in elements {
423 if let MaterialElement::Name(n) = e {
424 res.push(Material::default());
425 if let Some(l) = res.last_mut() {
426 l.name = n;
427 }
428 } else if let Some(l) = res.last_mut() {
429 l.set_from_material_element(&e);
430 } else {
431 return Err(MaterialError::NewMaterial);
432 }
433 }
434 Ok(res)
435}
436
437fn parse_material_set<'a>(
438) -> impl Parser<TokenSet<'a>, Output = Vec<MaterialElement>, Error = error::Error<TokenSet<'a>>> {
439 many1(alt((
440 alt((
441 parse_new_material(),
442 parse_ambient(),
443 parse_diffuse(),
444 parse_specular(),
445 parse_emissive_coefficient(),
446 parse_specular_exponent(),
447 parse_disolve(),
448 parse_transparency(),
449 parse_transmission_factor(),
450 parse_sharpness(),
451 parse_index_of_refraction(),
452 parse_illumination_model(),
453 parse_texture_map_ambient(),
454 parse_texture_map_diffuse(),
455 parse_texture_map_specular(),
456 )),
457 alt((
458 parse_shininess_map(),
459 parse_disolve_map(),
460 parse_displacement_map(),
461 parse_decal(),
462 parse_bump_map(),
463 parse_reflection_map(),
464 parse_anti_alias_map(),
465 )),
466 )))
467}
468
469fn parse_new_material<'a>(
470) -> impl Parser<TokenSet<'a>, Output = MaterialElement, Error = error::Error<TokenSet<'a>>> {
471 map(
472 preceded(
473 token_match!(Token::NewMaterial),
474 token_match!(Token::String(_)),
475 ),
476 |s| {
477 let name = match get_token_string(&s) {
478 Ok(s) => s,
479 Err(e) => {
480 log::error!("{}", e);
481 Default::default()
482 },
483 };
484 MaterialElement::Name(name.into())
485 },
486 )
487}
488
489fn parse_ambient<'a>(
490) -> impl Parser<TokenSet<'a>, Output = MaterialElement, Error = error::Error<TokenSet<'a>>> {
491 preceded(
492 token_match!(Token::AmbientColor),
493 map(parse_color_type(), MaterialElement::Ambient),
494 )
495}
496
497fn parse_diffuse<'a>(
498) -> impl Parser<TokenSet<'a>, Output = MaterialElement, Error = error::Error<TokenSet<'a>>> {
499 preceded(
500 token_match!(Token::DiffuseColor),
501 map(parse_color_type(), MaterialElement::Diffuse),
502 )
503}
504
505fn parse_specular<'a>(
506) -> impl Parser<TokenSet<'a>, Output = MaterialElement, Error = error::Error<TokenSet<'a>>> {
507 preceded(
508 token_match!(Token::SpecularColor),
509 map(parse_color_type(), MaterialElement::Specular),
510 )
511}
512
513fn parse_emissive_coefficient<'a>(
514) -> impl Parser<TokenSet<'a>, Output = MaterialElement, Error = error::Error<TokenSet<'a>>> {
515 preceded(
516 token_match!(Token::EmissiveCoefficient),
517 map(parse_color_type(), MaterialElement::EmissiveCoefficient),
518 )
519}
520
521fn parse_specular_exponent<'a>(
522) -> impl Parser<TokenSet<'a>, Output = MaterialElement, Error = error::Error<TokenSet<'a>>> {
523 preceded(
524 token_match!(Token::SpecularExponent),
525 map(token_match!(Token::Float(_) | Token::Int(_)), |f| {
526 let f = match get_token_float(&f) {
527 Ok(s) => s,
528 Err(e) => {
529 log::error!("{}", e);
530 Default::default()
531 },
532 };
533 MaterialElement::SpecularExponent(f)
534 }),
535 )
536}
537
538fn parse_disolve<'a>(
539) -> impl Parser<TokenSet<'a>, Output = MaterialElement, Error = error::Error<TokenSet<'a>>> {
540 preceded(
541 token_match!(Token::Disolved),
542 alt((
543 map(
544 preceded(
545 token_match!(Token::Halo),
546 token_match!(Token::Float(_) | Token::Int(_)),
547 ),
548 |f| {
549 let f = match get_token_float(&f) {
550 Ok(s) => s,
551 Err(e) => {
552 log::error!("{}", e);
553 Default::default()
554 },
555 };
556 MaterialElement::Disolve(DisolveType::Halo(f))
557 },
558 ),
559 map(token_match!(Token::Float(_) | Token::Int(_)), |f| {
560 let f = match get_token_float(&f) {
561 Ok(s) => s,
562 Err(e) => {
563 log::error!("{}", e);
564 Default::default()
565 },
566 };
567 MaterialElement::Disolve(DisolveType::Alpha(f))
568 }),
569 )),
570 )
571}
572
573fn parse_transparency<'a>(
574) -> impl Parser<TokenSet<'a>, Output = MaterialElement, Error = error::Error<TokenSet<'a>>> {
575 preceded(
576 token_match!(Token::Transparancy),
577 map(token_match!(Token::Float(_) | Token::Int(_)), |f| {
578 let f = match get_token_float(&f) {
579 Ok(s) => s,
580 Err(e) => {
581 log::error!("{}", e);
582 Default::default()
583 },
584 };
585 MaterialElement::Transparency(f)
586 }),
587 )
588}
589
590fn parse_transmission_factor<'a>(
591) -> impl Parser<TokenSet<'a>, Output = MaterialElement, Error = error::Error<TokenSet<'a>>> {
592 preceded(
593 token_match!(Token::TransmissionFactor),
594 map(parse_color_type(), MaterialElement::TransmissionFactor),
595 )
596}
597
598fn parse_sharpness<'a>(
599) -> impl Parser<TokenSet<'a>, Output = MaterialElement, Error = error::Error<TokenSet<'a>>> {
600 preceded(
601 token_match!(Token::Sharpness),
602 map(token_match!(Token::Float(_) | Token::Int(_)), |f| {
603 let f = match get_token_float(&f) {
604 Ok(s) => s,
605 Err(e) => {
606 log::error!("{}", e);
607 Default::default()
608 },
609 };
610 MaterialElement::Sharpness(f)
611 }),
612 )
613}
614
615fn parse_index_of_refraction<'a>(
616) -> impl Parser<TokenSet<'a>, Output = MaterialElement, Error = error::Error<TokenSet<'a>>> {
617 preceded(
618 token_match!(Token::IndexOfRefraction),
619 map(token_match!(Token::Float(_) | Token::Int(_)), |f| {
620 let f = match get_token_float(&f) {
621 Ok(s) => s,
622 Err(e) => {
623 log::error!("{}", e);
624 Default::default()
625 },
626 };
627 MaterialElement::IndexOfRefraction(f)
628 }),
629 )
630}
631
632fn parse_illumination_model<'a>(
633) -> impl Parser<TokenSet<'a>, Output = MaterialElement, Error = error::Error<TokenSet<'a>>> {
634 preceded(
635 token_match!(Token::IlluminationModel),
636 map(token_match!(Token::Int(_)), |f| {
637 let f = match get_token_int(&f) {
638 Ok(s) => s,
639 Err(e) => {
640 log::error!("{}", e);
641 Default::default()
642 },
643 };
644 MaterialElement::IlluminationModel(f as u32)
645 }),
646 )
647}
648
649fn parse_texture_map_ambient<'a>(
650) -> impl Parser<TokenSet<'a>, Output = MaterialElement, Error = error::Error<TokenSet<'a>>> {
651 preceded(
652 token_match!(Token::TextureMapAmbient),
653 map(parse_options(), |o| {
654 MaterialElement::TexMapAmbient(ColorCorrectedMap::new(&o))
655 }),
656 )
657}
658
659fn parse_texture_map_diffuse<'a>(
660) -> impl Parser<TokenSet<'a>, Output = MaterialElement, Error = error::Error<TokenSet<'a>>> {
661 preceded(
662 token_match!(Token::TextureMapDiffuse),
663 map(parse_options(), |o| {
664 MaterialElement::TexMapDiffuse(ColorCorrectedMap::new(&o))
665 }),
666 )
667}
668
669fn parse_texture_map_specular<'a>(
670) -> impl Parser<TokenSet<'a>, Output = MaterialElement, Error = error::Error<TokenSet<'a>>> {
671 preceded(
672 token_match!(Token::TextureMapSpecular),
673 map(parse_options(), |o| {
674 MaterialElement::TexMapSpecular(ColorCorrectedMap::new(&o))
675 }),
676 )
677}
678
679fn parse_shininess_map<'a>(
680) -> impl Parser<TokenSet<'a>, Output = MaterialElement, Error = error::Error<TokenSet<'a>>> {
681 preceded(
682 token_match!(Token::TextureMapShininess),
683 map(parse_options(), |o| {
684 MaterialElement::ShininessMap(NonColorCorrectedMap::new(&o))
685 }),
686 )
687}
688
689fn parse_disolve_map<'a>(
690) -> impl Parser<TokenSet<'a>, Output = MaterialElement, Error = error::Error<TokenSet<'a>>> {
691 preceded(
692 token_match!(Token::TextureMapDisolved),
693 map(parse_options(), |o| {
694 MaterialElement::DisolveMap(NonColorCorrectedMap::new(&o))
695 }),
696 )
697}
698
699fn parse_displacement_map<'a>(
700) -> impl Parser<TokenSet<'a>, Output = MaterialElement, Error = error::Error<TokenSet<'a>>> {
701 preceded(
702 token_match!(Token::DisplacementMap),
703 map(parse_options(), |o| {
704 MaterialElement::DisplacementMap(NonColorCorrectedMap::new(&o))
705 }),
706 )
707}
708
709fn parse_decal<'a>(
710) -> impl Parser<TokenSet<'a>, Output = MaterialElement, Error = error::Error<TokenSet<'a>>> {
711 preceded(
712 token_match!(Token::Decal),
713 map(parse_options(), |o| {
714 MaterialElement::Decal(NonColorCorrectedMap::new(&o))
715 }),
716 )
717}
718
719fn parse_bump_map<'a>(
720) -> impl Parser<TokenSet<'a>, Output = MaterialElement, Error = error::Error<TokenSet<'a>>> {
721 preceded(
722 token_match!(Token::BumpMap),
723 map(parse_options(), |o| {
724 MaterialElement::BumpMap(BumpMap::new(&o))
725 }),
726 )
727}
728
729fn parse_reflection_map<'a>(
730) -> impl Parser<TokenSet<'a>, Output = MaterialElement, Error = error::Error<TokenSet<'a>>> {
731 preceded(
732 token_match!(Token::ReflectionMap),
733 map(parse_options(), |o| {
734 MaterialElement::ReflectionMap(ReflectionMap::new(&o))
735 }),
736 )
737}
738
739fn parse_anti_alias_map<'a>(
740) -> impl Parser<TokenSet<'a>, Output = MaterialElement, Error = error::Error<TokenSet<'a>>> {
741 preceded(
742 token_match!(Token::AntiAliasMap),
743 map(token_match!(Token::String(_)), |o| {
744 let val = match get_on_off_from_str(&o) {
745 Ok(v) => v,
746 Err(e) => {
747 log::error!("{}", e);
748 Default::default()
749 },
750 };
751 MaterialElement::AntiAliasMap(val)
752 }),
753 )
754}
755
756fn parse_options<'a>(
757) -> impl Parser<TokenSet<'a>, Output = Vec<OptionElement>, Error = error::Error<TokenSet<'a>>> {
758 many1(alt((
759 parse_option_blend(),
760 parse_option_bm(),
761 parse_option_cc(),
762 parse_option_clamp(),
763 parse_option_texture_range(),
764 parse_option_offset(),
765 parse_option_scale(),
766 parse_option_turbulance(),
767 parse_option_texture_resolution(),
768 parse_option_imf_channel(),
769 parse_option_reflection_type(),
770 map(token_match!(Token::String(_)), |s| {
771 let name = match get_token_string(&s) {
772 Ok(s) => s,
773 Err(e) => {
774 log::error!("{}", e);
775 Default::default()
776 },
777 };
778 OptionElement::FileName(name.into())
779 }),
780 )))
781}
782
783fn parse_option_blend<'a>(
784) -> impl Parser<TokenSet<'a>, Output = OptionElement, Error = error::Error<TokenSet<'a>>> {
785 alt((
786 map(
787 preceded(
788 token_match!(Token::OptionBlendU),
789 token_match!(Token::String(_)),
790 ),
791 |s| {
792 let val = match get_on_off_from_str(&s) {
793 Ok(s) => s,
794 Err(e) => {
795 log::error!("{}", e);
796 Default::default()
797 },
798 };
799 OptionElement::BlendU(val)
800 },
801 ),
802 map(
803 preceded(
804 token_match!(Token::OptionBlendV),
805 token_match!(Token::String(_)),
806 ),
807 |s| {
808 let val = match get_on_off_from_str(&s) {
809 Ok(s) => s,
810 Err(e) => {
811 log::error!("{}", e);
812 Default::default()
813 },
814 };
815 OptionElement::BlendV(val)
816 },
817 ),
818 ))
819}
820
821fn parse_option_bm<'a>(
822) -> impl Parser<TokenSet<'a>, Output = OptionElement, Error = error::Error<TokenSet<'a>>> {
823 map(
824 preceded(
825 token_match!(Token::OptionBumpMultiplier),
826 token_match!(Token::Float(_) | Token::Int(_)),
827 ),
828 |s| {
829 let val = match get_token_float(&s) {
830 Ok(s) => s,
831 Err(e) => {
832 log::error!("{}", e);
833 Default::default()
834 },
835 };
836 OptionElement::BumpMultiplier(val)
837 },
838 )
839}
840
841fn parse_option_cc<'a>(
842) -> impl Parser<TokenSet<'a>, Output = OptionElement, Error = error::Error<TokenSet<'a>>> {
843 map(
844 preceded(
845 token_match!(Token::OptionColorCorrect),
846 token_match!(Token::String(_)),
847 ),
848 |s| {
849 let val = match get_on_off_from_str(&s) {
850 Ok(s) => s,
851 Err(e) => {
852 log::error!("{}", e);
853 Default::default()
854 },
855 };
856 OptionElement::Cc(val)
857 },
858 )
859}
860
861fn parse_option_clamp<'a>(
862) -> impl Parser<TokenSet<'a>, Output = OptionElement, Error = error::Error<TokenSet<'a>>> {
863 map(
864 preceded(
865 token_match!(Token::OptionClamp),
866 token_match!(Token::String(_)),
867 ),
868 |s| {
869 let val = match get_on_off_from_str(&s) {
870 Ok(s) => s,
871 Err(e) => {
872 log::error!("{}", e);
873 Default::default()
874 },
875 };
876 OptionElement::Clamp(val)
877 },
878 )
879}
880
881fn parse_option_texture_range<'a>(
882) -> impl Parser<TokenSet<'a>, Output = OptionElement, Error = error::Error<TokenSet<'a>>> {
883 map(
884 preceded(
885 token_match!(Token::OptionRange),
886 (
887 token_match!(Token::Float(_) | Token::Int(_)),
888 token_match!(Token::Float(_) | Token::Int(_)),
889 ),
890 ),
891 |(base, gain)| {
892 let base = match get_token_float(&base) {
893 Ok(s) => s,
894 Err(e) => {
895 log::error!("{}", e);
896 Default::default()
897 },
898 };
899 let gain = match get_token_float(&gain) {
900 Ok(s) => s,
901 Err(e) => {
902 log::error!("{}", e);
903 Default::default()
904 },
905 };
906 OptionElement::TextureRange((base, gain))
907 },
908 )
909}
910
911fn parse_option_offset<'a>(
912) -> impl Parser<TokenSet<'a>, Output = OptionElement, Error = error::Error<TokenSet<'a>>> {
913 map(
914 preceded(
915 token_match!(Token::OptionOffset),
916 (
917 token_match!(Token::Float(_) | Token::Int(_)),
918 opt(token_match!(Token::Float(_) | Token::Int(_))),
919 opt(token_match!(Token::Float(_) | Token::Int(_))),
920 ),
921 ),
922 |(x, y, z)| {
923 let x = match get_token_float(&x) {
924 Ok(s) => s,
925 Err(e) => {
926 log::error!("{}", e);
927 Default::default()
928 },
929 };
930 let y = match get_opt_token_float_opt(&y) {
931 Ok(s) => s,
932 Err(e) => {
933 log::error!("{}", e);
934 None
935 },
936 };
937 let z = match get_opt_token_float_opt(&z) {
938 Ok(s) => s,
939 Err(e) => {
940 log::error!("{}", e);
941 None
942 },
943 };
944 OptionElement::Offset((x, y, z))
945 },
946 )
947}
948
949fn parse_option_scale<'a>(
950) -> impl Parser<TokenSet<'a>, Output = OptionElement, Error = error::Error<TokenSet<'a>>> {
951 map(
952 preceded(
953 token_match!(Token::OptionScale),
954 (
955 token_match!(Token::Float(_) | Token::Int(_)),
956 opt(token_match!(Token::Float(_) | Token::Int(_))),
957 opt(token_match!(Token::Float(_) | Token::Int(_))),
958 ),
959 ),
960 |(x, y, z)| {
961 let x = match get_token_float(&x) {
962 Ok(s) => s,
963 Err(e) => {
964 log::error!("{}", e);
965 Default::default()
966 },
967 };
968 let y = match get_opt_token_float_opt(&y) {
969 Ok(s) => s,
970 Err(e) => {
971 log::error!("{}", e);
972 None
973 },
974 };
975 let z = match get_opt_token_float_opt(&z) {
976 Ok(s) => s,
977 Err(e) => {
978 log::error!("{}", e);
979 None
980 },
981 };
982 OptionElement::Scale((x, y, z))
983 },
984 )
985}
986
987fn parse_option_turbulance<'a>(
988) -> impl Parser<TokenSet<'a>, Output = OptionElement, Error = error::Error<TokenSet<'a>>> {
989 map(
990 preceded(
991 token_match!(Token::OptionTurbulence),
992 (
993 token_match!(Token::Float(_) | Token::Int(_)),
994 opt(token_match!(Token::Float(_) | Token::Int(_))),
995 opt(token_match!(Token::Float(_) | Token::Int(_))),
996 ),
997 ),
998 |(x, y, z)| {
999 let x = match get_token_float(&x) {
1000 Ok(s) => s,
1001 Err(e) => {
1002 log::error!("{}", e);
1003 Default::default()
1004 },
1005 };
1006 let y = match get_opt_token_float_opt(&y) {
1007 Ok(s) => s,
1008 Err(e) => {
1009 log::error!("{}", e);
1010 None
1011 },
1012 };
1013 let z = match get_opt_token_float_opt(&z) {
1014 Ok(s) => s,
1015 Err(e) => {
1016 log::error!("{}", e);
1017 None
1018 },
1019 };
1020 OptionElement::Turbulance((x, y, z))
1021 },
1022 )
1023}
1024
1025fn parse_option_texture_resolution<'a>(
1026) -> impl Parser<TokenSet<'a>, Output = OptionElement, Error = error::Error<TokenSet<'a>>> {
1027 map(
1028 preceded(
1029 token_match!(Token::OptionTextureResolution),
1030 token_match!(Token::Int(_)),
1031 ),
1032 |s| {
1033 let val = match get_token_int(&s) {
1034 Ok(s) => s,
1035 Err(e) => {
1036 log::error!("{}", e);
1037 Default::default()
1038 },
1039 };
1040 OptionElement::TextureRes(val)
1041 },
1042 )
1043}
1044
1045fn parse_option_imf_channel<'a>(
1046) -> impl Parser<TokenSet<'a>, Output = OptionElement, Error = error::Error<TokenSet<'a>>> {
1047 map(
1048 preceded(
1049 token_match!(Token::OptionIMFChan),
1050 token_match!(Token::String(_)),
1051 ),
1052 |s| {
1053 let val = match get_token_string(&s) {
1054 Ok(s) => s,
1055 Err(e) => {
1056 log::error!("{}", e);
1057 Default::default()
1058 },
1059 };
1060 OptionElement::ImfChan(val.into())
1061 },
1062 )
1063}
1064
1065fn parse_option_reflection_type<'a>(
1066) -> impl Parser<TokenSet<'a>, Output = OptionElement, Error = error::Error<TokenSet<'a>>> {
1067 map(
1068 preceded(
1069 token_match!(Token::ReflectionType),
1070 token_match!(Token::String(_)),
1071 ),
1072 |s| {
1073 let val = match get_token_string(&s) {
1074 Ok(s) => s,
1075 Err(e) => {
1076 log::error!("{}", e);
1077 Default::default()
1078 },
1079 };
1080 OptionElement::ReflectionType(val.into())
1081 },
1082 )
1083}
1084
1085fn parse_color_type<'a>(
1086) -> impl Parser<TokenSet<'a>, Output = ColorType, Error = error::Error<TokenSet<'a>>> {
1087 alt((
1088 map(
1089 (
1090 token_match!(Token::Spectral),
1091 token_match!(Token::String(_)),
1092 opt(token_match!(Token::Float(_) | Token::Int(_))),
1093 ),
1094 |(_, file, factor)| {
1095 let file_name = match get_token_string(&file) {
1096 Ok(s) => s,
1097 Err(e) => {
1098 log::error!("{}", e);
1099 Default::default()
1100 },
1101 };
1102 let factor = match get_opt_token_float_opt(&factor) {
1103 Ok(s) => s.unwrap_or(1.0),
1104 Err(e) => {
1105 log::error!("{}", e);
1106 Default::default()
1107 },
1108 };
1109 ColorType::Spectral(file_name.into(), factor)
1110 },
1111 ),
1112 map(
1113 (
1114 token_match!(Token::Xyz),
1115 token_match!(Token::Float(_) | Token::Int(_)),
1116 opt(token_match!(Token::Float(_) | Token::Int(_))),
1117 opt(token_match!(Token::Float(_) | Token::Int(_))),
1118 ),
1119 |(_, x_token, y_token, z_token)| {
1120 let x = match get_token_float(&x_token) {
1121 Ok(s) => s,
1122 Err(e) => {
1123 log::error!("{}", e);
1124 Default::default()
1125 },
1126 };
1127 let y = match y_token {
1128 Some(y) => match get_token_float(&y) {
1129 Ok(s) => s,
1130 Err(e) => {
1131 log::error!("{}", e);
1132 Default::default()
1133 },
1134 },
1135 None => x,
1136 };
1137 let z = match z_token {
1138 Some(z) => match get_token_float(&z) {
1139 Ok(s) => s,
1140 Err(e) => {
1141 log::error!("{}", e);
1142 Default::default()
1143 },
1144 },
1145 None => x,
1146 };
1147
1148 ColorType::CieXyz(x, y, z)
1149 },
1150 ),
1151 map(
1152 (
1153 token_match!(Token::Float(_) | Token::Int(_)),
1154 token_match!(Token::Float(_) | Token::Int(_)),
1155 token_match!(Token::Float(_) | Token::Int(_)),
1156 ),
1157 |(r, g, b)| {
1158 let (r, g, b) = (
1159 match get_token_float(&r) {
1160 Ok(s) => s,
1161 Err(e) => {
1162 log::error!("{}", e);
1163 Default::default()
1164 },
1165 },
1166 match get_token_float(&g) {
1167 Ok(s) => s,
1168 Err(e) => {
1169 log::error!("{}", e);
1170 Default::default()
1171 },
1172 },
1173 match get_token_float(&b) {
1174 Ok(s) => s,
1175 Err(e) => {
1176 log::error!("{}", e);
1177 Default::default()
1178 },
1179 },
1180 );
1181
1182 ColorType::Rgb(r, g, b)
1183 },
1184 ),
1185 ))
1186}