1use crate::io_ext::{ReadExt, WriteExt};
2use std::io::{Read, Seek, Write};
3
4use crate::common::{M2Array, M2Parse, M2Vec};
5use crate::error::Result;
6use crate::version::M2Version;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub enum M2InterpolationType {
11 None = 0,
13 Linear = 1,
15 Bezier = 2,
17 Hermite = 3,
19}
20
21impl M2InterpolationType {
22 pub fn from_u16(value: u16) -> Option<Self> {
24 match value {
25 0 => Some(Self::None),
26 1 => Some(Self::Linear),
27 2 => Some(Self::Bezier),
28 3 => Some(Self::Hermite),
29 _ => None,
30 }
31 }
32}
33
34bitflags::bitflags! {
35 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
37 pub struct M2AnimationFlags: u16 {
38 const HAS_TRANSLATION = 0x1;
40 const HAS_ROTATION = 0x2;
42 const HAS_SCALING = 0x4;
44 const WORLD_SPACE = 0x8;
46 const BILLBOARD_ROTATION = 0x10;
48 }
49}
50
51#[derive(Debug, Clone, Copy, PartialEq)]
53pub struct M2Range {
54 pub minimum: f32,
56 pub maximum: f32,
58}
59
60impl M2Range {
61 pub fn parse<R: Read>(reader: &mut R) -> Result<Self> {
63 let minimum = reader.read_f32_le()?;
64 let maximum = reader.read_f32_le()?;
65
66 Ok(Self { minimum, maximum })
67 }
68
69 pub fn write<W: Write>(&self, writer: &mut W) -> Result<()> {
71 writer.write_f32_le(self.minimum)?;
72 writer.write_f32_le(self.maximum)?;
73
74 Ok(())
75 }
76}
77
78#[derive(Debug, Clone)]
80pub struct M2AnimationTrack<T: M2Parse> {
81 pub interpolation_type: M2InterpolationType,
83 pub global_sequence: i16,
85 pub interpolation_ranges: M2Array<(u32, u32)>,
87 pub timestamps: M2Array<u32>,
89 pub values: M2Vec<T>,
91}
92
93impl<T: M2Parse> Default for M2AnimationTrack<T> {
94 fn default() -> Self {
95 Self {
96 interpolation_type: M2InterpolationType::None,
97 global_sequence: -1,
98 interpolation_ranges: M2Array::new(0, 0),
99 timestamps: M2Array::new(0, 0),
100 values: M2Vec::new(),
101 }
102 }
103}
104
105impl<T: M2Parse> M2AnimationTrack<T> {
106 pub fn parse<R: Read + Seek>(reader: &mut R) -> Result<Self> {
108 let interpolation_type_raw = reader.read_u16_le()?;
109 let interpolation_type = M2InterpolationType::from_u16(interpolation_type_raw)
110 .unwrap_or(M2InterpolationType::None);
111
112 let global_sequence = reader.read_i16_le()?;
113 let interpolation_ranges = M2Array::parse(reader)?;
114 let timestamps = M2Array::parse(reader)?;
115 let values = M2Vec::<T>::parse(reader)?;
116
117 Ok(Self {
118 interpolation_type,
119 global_sequence,
120 interpolation_ranges,
121 timestamps,
122 values,
123 })
124 }
125
126 pub fn write<W: Write>(&self, writer: &mut W) -> Result<()> {
128 writer.write_u16_le(self.interpolation_type as u16)?;
129 writer.write_i16_le(self.global_sequence)?;
130 self.interpolation_ranges.write(writer)?;
131 self.timestamps.write(writer)?;
132 self.values.write(writer)?;
133
134 Ok(())
135 }
136}
137
138#[derive(Debug, Default, Clone)]
140pub struct M2AnimationBlock<T: M2Parse> {
141 pub track: M2AnimationTrack<T>,
143 _phantom: std::marker::PhantomData<T>,
145}
146
147impl<T: M2Parse> M2AnimationBlock<T> {
148 pub fn new(track: M2AnimationTrack<T>) -> Self {
150 Self {
151 track,
152 _phantom: std::marker::PhantomData,
153 }
154 }
155
156 pub fn parse<R: Read + Seek>(reader: &mut R) -> Result<Self> {
158 let track = M2AnimationTrack::parse(reader)?;
159
160 Ok(Self {
161 track,
162 _phantom: std::marker::PhantomData,
163 })
164 }
165
166 pub fn write<W: Write>(&self, writer: &mut W) -> Result<()> {
168 self.track.write(writer)?;
169
170 Ok(())
171 }
172}
173
174#[derive(Debug, Clone)]
176pub struct M2Animation {
177 pub animation_id: u16,
179 pub sub_animation_id: u16,
181 pub start_timestamp: u32,
183 pub end_timestamp: Option<u32>,
185 pub movement_speed: f32,
187 pub flags: u32,
189 pub frequency: i16,
191 pub padding: u16,
193 pub replay: Option<M2Range>,
195 pub minimum_extent: Option<[f32; 3]>,
197 pub maximum_extent: Option<[f32; 3]>,
199 pub extent_radius: Option<f32>,
201 pub next_animation: Option<i16>,
203 pub aliasing: Option<u16>,
205}
206
207impl M2Animation {
208 pub fn parse<R: Read>(reader: &mut R, version: u32) -> Result<Self> {
210 let animation_id = reader.read_u16_le()?;
211 let sub_animation_id = reader.read_u16_le()?;
212
213 if version <= 256 {
215 let start_timestamp = reader.read_u32_le()?;
217 let end_timestamp = reader.read_u32_le()?;
218 let movement_speed = reader.read_f32_le()?;
219 let flags = reader.read_u32_le()?;
220 let frequency = reader.read_i16_le()?;
221 let padding = reader.read_u16_le()?;
222 let replay = M2Range::parse(reader)?;
223
224 Ok(Self {
225 animation_id,
226 sub_animation_id,
227 start_timestamp,
228 end_timestamp: Some(end_timestamp),
229 movement_speed,
230 flags,
231 frequency,
232 padding,
233 replay: Some(replay),
234 minimum_extent: None,
235 maximum_extent: None,
236 extent_radius: None,
237 next_animation: None,
238 aliasing: None,
239 })
240 } else {
241 let duration = reader.read_u32_le()?;
243 let movement_speed = reader.read_f32_le()?;
244 let flags = reader.read_u32_le()?;
245 let frequency = reader.read_i16_le()?;
246 let padding = reader.read_u16_le()?;
247
248 let mut minimum_extent = [0.0; 3];
249 let mut maximum_extent = [0.0; 3];
250
251 for item in &mut minimum_extent {
252 *item = reader.read_f32_le()?;
253 }
254
255 for item in &mut maximum_extent {
256 *item = reader.read_f32_le()?;
257 }
258
259 let extent_radius = reader.read_f32_le()?;
260 let next_animation = reader.read_i16_le()?;
261 let aliasing = reader.read_u16_le()?;
262
263 Ok(Self {
264 animation_id,
265 sub_animation_id,
266 start_timestamp: duration, end_timestamp: None,
268 movement_speed,
269 flags,
270 frequency,
271 padding,
272 replay: None,
273 minimum_extent: Some(minimum_extent),
274 maximum_extent: Some(maximum_extent),
275 extent_radius: Some(extent_radius),
276 next_animation: Some(next_animation),
277 aliasing: Some(aliasing),
278 })
279 }
280 }
281
282 pub fn write<W: Write>(&self, writer: &mut W, version: u32) -> Result<()> {
284 writer.write_u16_le(self.animation_id)?;
285 writer.write_u16_le(self.sub_animation_id)?;
286
287 if version <= 256 {
288 writer.write_u32_le(self.start_timestamp)?;
290 writer.write_u32_le(self.end_timestamp.unwrap_or(self.start_timestamp + 1000))?;
291 writer.write_f32_le(self.movement_speed)?;
292 writer.write_u32_le(self.flags)?;
293 writer.write_i16_le(self.frequency)?;
294 writer.write_u16_le(self.padding)?;
295
296 if let Some(replay) = &self.replay {
297 replay.write(writer)?;
298 } else {
299 M2Range {
301 minimum: 0.0,
302 maximum: 1.0,
303 }
304 .write(writer)?;
305 }
306 } else {
307 writer.write_u32_le(self.start_timestamp)?; writer.write_f32_le(self.movement_speed)?;
310 writer.write_u32_le(self.flags)?;
311 writer.write_i16_le(self.frequency)?;
312 writer.write_u16_le(self.padding)?;
313
314 let minimum_extent = self.minimum_extent.unwrap_or([0.0, 0.0, 0.0]);
315 let maximum_extent = self.maximum_extent.unwrap_or([0.0, 0.0, 0.0]);
316
317 for &value in &minimum_extent {
318 writer.write_f32_le(value)?;
319 }
320
321 for &value in &maximum_extent {
322 writer.write_f32_le(value)?;
323 }
324
325 writer.write_f32_le(self.extent_radius.unwrap_or(0.0))?;
326 writer.write_i16_le(self.next_animation.unwrap_or(-1))?;
327 writer.write_u16_le(self.aliasing.unwrap_or(0))?;
328 }
329
330 Ok(())
331 }
332
333 pub fn convert(&self, _target_version: M2Version) -> Self {
335 self.clone()
336 }
337}