wow_m2/chunks/
texture_transform.rs1use crate::io_ext::{ReadExt, WriteExt};
2use std::io::{Read, Seek, Write};
3
4use crate::chunks::animation::{M2AnimationBlock, M2AnimationTrack};
5use crate::common::{C3Vector, M2Parse};
6use crate::error::Result;
7use crate::version::M2Version;
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub enum M2TextureTransformType {
12 None = 0,
14 Scroll = 1,
16 Rotate = 2,
18 Scale = 3,
20 Matrix = 4,
22}
23
24impl M2TextureTransformType {
25 pub fn from_u16(value: u16) -> Option<Self> {
27 match value {
28 0 => Some(Self::None),
29 1 => Some(Self::Scroll),
30 2 => Some(Self::Rotate),
31 3 => Some(Self::Scale),
32 4 => Some(Self::Matrix),
33 _ => None,
34 }
35 }
36}
37
38#[derive(Debug, Clone)]
41pub struct M2TextureTransform {
42 pub id: u32,
44 pub transform_type: M2TextureTransformType,
46 pub translation: M2AnimationBlock<C3Vector>,
48 pub rotation: M2AnimationBlock<C4Quaternion>,
50 pub scaling: M2AnimationBlock<C3Vector>,
52}
53
54#[derive(Debug, Clone, Copy, PartialEq)]
56pub struct C4Quaternion {
57 pub x: f32,
58 pub y: f32,
59 pub z: f32,
60 pub w: f32,
61}
62
63impl M2Parse for C4Quaternion {
64 fn parse<R: Read + Seek>(reader: &mut R) -> Result<Self> {
65 C4Quaternion::parse(reader)
66 }
67
68 fn write<W: Write>(&self, writer: &mut W) -> Result<()> {
69 self.write(writer)
70 }
71}
72
73impl C4Quaternion {
74 pub fn parse<R: Read>(reader: &mut R) -> Result<Self> {
76 let x = reader.read_f32_le()?;
77 let y = reader.read_f32_le()?;
78 let z = reader.read_f32_le()?;
79 let w = reader.read_f32_le()?;
80
81 Ok(Self { x, y, z, w })
82 }
83
84 pub fn write<W: Write>(&self, writer: &mut W) -> Result<()> {
86 writer.write_f32_le(self.x)?;
87 writer.write_f32_le(self.y)?;
88 writer.write_f32_le(self.z)?;
89 writer.write_f32_le(self.w)?;
90
91 Ok(())
92 }
93}
94
95impl M2TextureTransform {
96 pub fn parse<R: Read + Seek>(reader: &mut R) -> Result<Self> {
98 let id = reader.read_u32_le()?;
99
100 let transform_type_raw = reader.read_u16_le()?;
101 let transform_type = M2TextureTransformType::from_u16(transform_type_raw)
102 .unwrap_or(M2TextureTransformType::None);
103
104 reader.read_u16_le()?;
106
107 let translation = M2AnimationBlock::parse(reader)?;
108 let rotation = M2AnimationBlock::parse(reader)?;
109 let scaling = M2AnimationBlock::parse(reader)?;
110
111 Ok(Self {
112 id,
113 transform_type,
114 translation,
115 rotation,
116 scaling,
117 })
118 }
119
120 pub fn write<W: Write>(&self, writer: &mut W) -> Result<()> {
122 writer.write_u32_le(self.id)?;
123 writer.write_u16_le(self.transform_type as u16)?;
124
125 writer.write_u16_le(0)?;
127
128 self.translation.write(writer)?;
129 self.rotation.write(writer)?;
130 self.scaling.write(writer)?;
131
132 Ok(())
133 }
134
135 pub fn convert(&self, _target_version: M2Version) -> Self {
137 self.clone()
139 }
140
141 pub fn new(id: u32, transform_type: M2TextureTransformType) -> Self {
143 Self {
144 id,
145 transform_type,
146 translation: M2AnimationBlock::new(M2AnimationTrack::default()),
147 rotation: M2AnimationBlock::new(M2AnimationTrack::default()),
148 scaling: M2AnimationBlock::new(M2AnimationTrack::default()),
149 }
150 }
151}
152
153#[cfg(test)]
154mod tests {
155 use super::*;
156 use std::io::Cursor;
157
158 #[test]
159 fn test_c4quaternion_parse_write() {
160 let quat = C4Quaternion {
161 x: 0.0,
162 y: 0.0,
163 z: 0.0,
164 w: 1.0,
165 };
166
167 let mut data = Vec::new();
168 quat.write(&mut data).unwrap();
169
170 let mut cursor = Cursor::new(data);
171 let parsed_quat = C4Quaternion::parse(&mut cursor).unwrap();
172
173 assert_eq!(parsed_quat.x, 0.0);
174 assert_eq!(parsed_quat.y, 0.0);
175 assert_eq!(parsed_quat.z, 0.0);
176 assert_eq!(parsed_quat.w, 1.0);
177 }
178
179 #[test]
180 fn test_texture_transform_type() {
181 assert_eq!(
182 M2TextureTransformType::from_u16(0),
183 Some(M2TextureTransformType::None)
184 );
185 assert_eq!(
186 M2TextureTransformType::from_u16(1),
187 Some(M2TextureTransformType::Scroll)
188 );
189 assert_eq!(
190 M2TextureTransformType::from_u16(2),
191 Some(M2TextureTransformType::Rotate)
192 );
193 assert_eq!(
194 M2TextureTransformType::from_u16(3),
195 Some(M2TextureTransformType::Scale)
196 );
197 assert_eq!(
198 M2TextureTransformType::from_u16(4),
199 Some(M2TextureTransformType::Matrix)
200 );
201 assert_eq!(M2TextureTransformType::from_u16(5), None);
202 }
203}