vmt_parser/data/
texture_transform.rs

1use serde::de::Error;
2use serde::{Deserialize, Deserializer, Serialize, Serializer};
3use std::borrow::Cow;
4use std::fmt::{Display, Formatter};
5use std::str::FromStr;
6
7#[derive(Debug, PartialEq, Clone)]
8pub struct TextureTransform {
9    pub center: [f32; 2],
10    pub scale: [f32; 2],
11    pub rotate: f32,
12    pub translate: [f32; 2],
13}
14
15impl Default for TextureTransform {
16    fn default() -> Self {
17        TextureTransform {
18            center: [0.5; 2],
19            scale: [1.0; 2],
20            rotate: 0.0,
21            translate: [0.0; 2],
22        }
23    }
24}
25
26impl Display for TextureTransform {
27    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
28        write!(
29            f,
30            "center {} {} scale {} {} rotate {} translate {} {}",
31            self.center[0],
32            self.center[1],
33            self.scale[0],
34            self.scale[1],
35            self.rotate,
36            self.translate[0],
37            self.translate[1],
38        )
39    }
40}
41
42#[test]
43fn test_parse_base_texture_transform() {
44    assert_eq!(
45        TextureTransform {
46            center: [0.5; 2],
47            scale: [1.0; 2],
48            rotate: 0.0,
49            translate: [0.0; 2],
50        },
51        TextureTransform::from_str("center .5 .5 scale 1 1 rotate 0 translate 0 0").unwrap()
52    );
53    assert_eq!(
54        TextureTransform {
55            center: [0.2, 0.3],
56            scale: [1.1, 1.2],
57            rotate: 1.0,
58            translate: [0.4, 0.5],
59        },
60        TextureTransform::from_str("center .2 .3 scale 1.1 1.2 rotate 1 translate 0.4 0.5")
61            .unwrap()
62    );
63}
64
65impl FromStr for TextureTransform {
66    type Err = &'static str;
67
68    fn from_str(str: &str) -> Result<Self, Self::Err> {
69        let mut parts = str.split(' ').filter(|p| !p.is_empty());
70        match (
71            parts.next(),
72            parts.next().and_then(|val| f32::from_str(val).ok()),
73            parts.next().and_then(|val| f32::from_str(val).ok()),
74            parts.next(),
75            parts.next().and_then(|val| f32::from_str(val).ok()),
76            parts.next().and_then(|val| f32::from_str(val).ok()),
77            parts.next(),
78            parts.next().and_then(|val| f32::from_str(val).ok()),
79            parts.next(),
80            parts.next().and_then(|val| f32::from_str(val).ok()),
81            parts.next().and_then(|val| f32::from_str(val).ok()),
82        ) {
83            (
84                Some("center"),
85                Some(center_x),
86                Some(center_y),
87                Some("scale"),
88                Some(scale_x),
89                Some(scale_y),
90                Some("rotate"),
91                Some(rotate),
92                Some("translate"),
93                Some(translate_x),
94                Some(translate_y),
95            ) => Ok(TextureTransform {
96                center: [center_x, center_y],
97                scale: [scale_x, scale_y],
98                rotate,
99                translate: [translate_x, translate_y],
100            }),
101            _ => Err("invalid $basetexturetransform format"),
102        }
103    }
104}
105
106impl<'de> Deserialize<'de> for TextureTransform {
107    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
108    where
109        D: Deserializer<'de>,
110    {
111        let str = Cow::<str>::deserialize(deserializer)?;
112        Self::from_str(str.as_ref()).map_err(D::Error::custom)
113    }
114}
115
116impl Serialize for TextureTransform {
117    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
118    where
119        S: Serializer,
120    {
121        serializer.serialize_str(&self.to_string())
122    }
123}