1use crate::io_ext::{ReadExt, WriteExt};
2use std::io::{Read, Write};
3
4use crate::common::M2Array;
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 {
81 pub interpolation_type: M2InterpolationType,
83 pub global_sequence: i16,
85 pub timestamps: M2Array<u32>,
87 pub values: M2Array<f32>,
89}
90
91impl M2AnimationTrack {
92 pub fn parse<R: Read>(reader: &mut R) -> Result<Self> {
94 let interpolation_type_raw = reader.read_u16_le()?;
95 let interpolation_type = M2InterpolationType::from_u16(interpolation_type_raw)
96 .unwrap_or(M2InterpolationType::None);
97
98 let global_sequence = reader.read_i16_le()?;
99 let timestamps = M2Array::parse(reader)?;
100 let values = M2Array::parse(reader)?;
101
102 Ok(Self {
103 interpolation_type,
104 global_sequence,
105 timestamps,
106 values,
107 })
108 }
109
110 pub fn write<W: Write>(&self, writer: &mut W) -> Result<()> {
112 writer.write_u16_le(self.interpolation_type as u16)?;
113 writer.write_i16_le(self.global_sequence)?;
114 self.timestamps.write(writer)?;
115 self.values.write(writer)?;
116
117 Ok(())
118 }
119}
120
121#[derive(Debug, Clone)]
123pub struct M2AnimationBlock<T> {
124 pub track: M2AnimationTrack,
126 _phantom: std::marker::PhantomData<T>,
128}
129
130impl<T> M2AnimationBlock<T> {
131 pub fn new(track: M2AnimationTrack) -> Self {
133 Self {
134 track,
135 _phantom: std::marker::PhantomData,
136 }
137 }
138
139 pub fn parse<R: Read>(reader: &mut R) -> Result<Self> {
141 let track = M2AnimationTrack::parse(reader)?;
142
143 Ok(Self {
144 track,
145 _phantom: std::marker::PhantomData,
146 })
147 }
148
149 pub fn write<W: Write>(&self, writer: &mut W) -> Result<()> {
151 self.track.write(writer)?;
152
153 Ok(())
154 }
155}
156
157#[derive(Debug, Clone)]
159pub struct M2Animation {
160 pub animation_id: u16,
162 pub sub_animation_id: u16,
164 pub start_timestamp: u32,
166 pub end_timestamp: Option<u32>,
168 pub movement_speed: f32,
170 pub flags: u32,
172 pub frequency: i16,
174 pub padding: u16,
176 pub replay: Option<M2Range>,
178 pub minimum_extent: Option<[f32; 3]>,
180 pub maximum_extent: Option<[f32; 3]>,
182 pub extent_radius: Option<f32>,
184 pub next_animation: Option<i16>,
186 pub aliasing: Option<u16>,
188}
189
190impl M2Animation {
191 pub fn parse<R: Read>(reader: &mut R, version: u32) -> Result<Self> {
193 let animation_id = reader.read_u16_le()?;
194 let sub_animation_id = reader.read_u16_le()?;
195
196 if version <= 256 {
198 let start_timestamp = reader.read_u32_le()?;
200 let end_timestamp = reader.read_u32_le()?;
201 let movement_speed = reader.read_f32_le()?;
202 let flags = reader.read_u32_le()?;
203 let frequency = reader.read_i16_le()?;
204 let padding = reader.read_u16_le()?;
205 let replay = M2Range::parse(reader)?;
206
207 Ok(Self {
208 animation_id,
209 sub_animation_id,
210 start_timestamp,
211 end_timestamp: Some(end_timestamp),
212 movement_speed,
213 flags,
214 frequency,
215 padding,
216 replay: Some(replay),
217 minimum_extent: None,
218 maximum_extent: None,
219 extent_radius: None,
220 next_animation: None,
221 aliasing: None,
222 })
223 } else {
224 let duration = reader.read_u32_le()?;
226 let movement_speed = reader.read_f32_le()?;
227 let flags = reader.read_u32_le()?;
228 let frequency = reader.read_i16_le()?;
229 let padding = reader.read_u16_le()?;
230
231 let mut minimum_extent = [0.0; 3];
232 let mut maximum_extent = [0.0; 3];
233
234 for item in &mut minimum_extent {
235 *item = reader.read_f32_le()?;
236 }
237
238 for item in &mut maximum_extent {
239 *item = reader.read_f32_le()?;
240 }
241
242 let extent_radius = reader.read_f32_le()?;
243 let next_animation = reader.read_i16_le()?;
244 let aliasing = reader.read_u16_le()?;
245
246 Ok(Self {
247 animation_id,
248 sub_animation_id,
249 start_timestamp: duration, end_timestamp: None,
251 movement_speed,
252 flags,
253 frequency,
254 padding,
255 replay: None,
256 minimum_extent: Some(minimum_extent),
257 maximum_extent: Some(maximum_extent),
258 extent_radius: Some(extent_radius),
259 next_animation: Some(next_animation),
260 aliasing: Some(aliasing),
261 })
262 }
263 }
264
265 pub fn write<W: Write>(&self, writer: &mut W, version: u32) -> Result<()> {
267 writer.write_u16_le(self.animation_id)?;
268 writer.write_u16_le(self.sub_animation_id)?;
269
270 if version <= 256 {
271 writer.write_u32_le(self.start_timestamp)?;
273 writer.write_u32_le(self.end_timestamp.unwrap_or(self.start_timestamp + 1000))?;
274 writer.write_f32_le(self.movement_speed)?;
275 writer.write_u32_le(self.flags)?;
276 writer.write_i16_le(self.frequency)?;
277 writer.write_u16_le(self.padding)?;
278
279 if let Some(replay) = &self.replay {
280 replay.write(writer)?;
281 } else {
282 M2Range {
284 minimum: 0.0,
285 maximum: 1.0,
286 }
287 .write(writer)?;
288 }
289 } else {
290 writer.write_u32_le(self.start_timestamp)?; writer.write_f32_le(self.movement_speed)?;
293 writer.write_u32_le(self.flags)?;
294 writer.write_i16_le(self.frequency)?;
295 writer.write_u16_le(self.padding)?;
296
297 let minimum_extent = self.minimum_extent.unwrap_or([0.0, 0.0, 0.0]);
298 let maximum_extent = self.maximum_extent.unwrap_or([0.0, 0.0, 0.0]);
299
300 for &value in &minimum_extent {
301 writer.write_f32_le(value)?;
302 }
303
304 for &value in &maximum_extent {
305 writer.write_f32_le(value)?;
306 }
307
308 writer.write_f32_le(self.extent_radius.unwrap_or(0.0))?;
309 writer.write_i16_le(self.next_animation.unwrap_or(-1))?;
310 writer.write_u16_le(self.aliasing.unwrap_or(0))?;
311 }
312
313 Ok(())
314 }
315
316 pub fn convert(&self, _target_version: M2Version) -> Self {
318 self.clone()
319 }
320}