source: OniSplit/Totoro/AnimationDatReader.cs@ 1168

Last change on this file since 1168 was 1114, checked in by iritscen, 5 years ago

Adding OniSplit source code (v0.9.99.0). Many thanks to Neo for all his work over the years.

File size: 14.6 KB
RevLine 
[1114]1using System;
2using System.Collections.Generic;
3
4namespace Oni.Totoro
5{
6 internal class AnimationDatReader
7 {
8 private readonly Animation animation = new Animation();
9 private readonly InstanceDescriptor tram;
10 private readonly BinaryReader dat;
11
12 #region private class DatExtent
13
14 private class DatExtent
15 {
16 public int Frame;
17 public readonly AttackExtent Extent = new AttackExtent();
18 }
19
20 #endregion
21 #region private class DatExtentInfo
22
23 private class DatExtentInfo
24 {
25 public float MaxHorizontal;
26 public float MinY = 1e09f;
27 public float MaxY = -1e09f;
28 public readonly DatExtentInfoFrame FirstExtent = new DatExtentInfoFrame();
29 public readonly DatExtentInfoFrame MaxExtent = new DatExtentInfoFrame();
30 }
31
32 #endregion
33 #region private class DatExtentInfoFrame
34
35 private class DatExtentInfoFrame
36 {
37 public int Frame = -1;
38 public int Attack;
39 public int AttackOffset;
40 public Vector2 Location;
41 public float Height;
42 public float Length;
43 public float MinY;
44 public float MaxY;
45 public float Angle;
46 }
47
48 #endregion
49
50 private AnimationDatReader(InstanceDescriptor tram, BinaryReader dat)
51 {
52 this.tram = tram;
53 this.dat = dat;
54 }
55
56 public static Animation Read(InstanceDescriptor tram)
57 {
58 using (var dat = tram.OpenRead())
59 {
60 var reader = new AnimationDatReader(tram, dat);
61 reader.ReadAnimation();
62 return reader.animation;
63 }
64 }
65
66 private void ReadAnimation()
67 {
68 dat.Skip(4);
69 int heightOffset = dat.ReadInt32();
70 int velocityOffset = dat.ReadInt32();
71 int attackOffset = dat.ReadInt32();
72 int damageOffset = dat.ReadInt32();
73 int motionBlurOffset = dat.ReadInt32();
74 int shortcutOffset = dat.ReadInt32();
75 ReadOptionalThrowInfo();
76 int footstepOffset = dat.ReadInt32();
77 int particleOffset = dat.ReadInt32();
78 int positionOffset = dat.ReadInt32();
79 int rotationOffset = dat.ReadInt32();
80 int soundOffset = dat.ReadInt32();
81 animation.Flags = (AnimationFlags)dat.ReadInt32();
82
83 var directAnimations = dat.ReadLinkArray(2);
84 for (int i = 0; i < directAnimations.Length; i++)
85 animation.DirectAnimations[i] = (directAnimations[i] != null ? directAnimations[i].FullName : null);
86
87 animation.OverlayUsedBones = (BoneMask)dat.ReadInt32();
88 animation.OverlayReplacedBones = (BoneMask)dat.ReadInt32();
89 animation.FinalRotation = dat.ReadSingle();
90 animation.Direction = (Direction)dat.ReadUInt16();
91 animation.Vocalization = dat.ReadUInt16();
92 var extents = ReadExtentInfo();
93 animation.Impact = dat.ReadString(16);
94 animation.HardPause = dat.ReadUInt16();
95 animation.SoftPause = dat.ReadUInt16();
96 int soundCount = dat.ReadInt32();
97 dat.Skip(6);
98 int fps = dat.ReadUInt16();
99 animation.FrameSize = dat.ReadUInt16();
100 animation.Type = (AnimationType)dat.ReadUInt16();
101 animation.AimingType = (AnimationType)dat.ReadUInt16();
102 animation.FromState = (AnimationState)dat.ReadUInt16();
103 animation.ToState = (AnimationState)dat.ReadUInt16();
104 int boneCount = dat.ReadUInt16();
105 int frameCount = dat.ReadUInt16();
106 int duration = dat.ReadInt16();
107 animation.Varient = (AnimationVarient)dat.ReadUInt16();
108 dat.Skip(2);
109 animation.AtomicStart = dat.ReadUInt16();
110 animation.AtomicEnd = dat.ReadUInt16();
111 animation.InterpolationEnd = dat.ReadUInt16();
112 animation.InterpolationMax = dat.ReadUInt16();
113 animation.ActionFrame = dat.ReadUInt16();
114 animation.FirstLevelAvailable = dat.ReadUInt16();
115 animation.InvulnerableStart = dat.ReadByte();
116 animation.InvulnerableEnd = dat.ReadByte();
117 int attackCount = dat.ReadByte();
118 int damageCount = dat.ReadByte();
119 int motionBlurCount = dat.ReadByte();
120 int shortcutCount = dat.ReadByte();
121 int footstepCount = dat.ReadByte();
122 int particleCount = dat.ReadByte();
123 ReadRawArray(heightOffset, frameCount, animation.Heights, r => r.ReadSingle());
124 ReadRawArray(velocityOffset, frameCount, animation.Velocities, r => r.ReadVector2());
125 ReadRotations(rotationOffset, boneCount, frameCount);
126 ReadRawArray(positionOffset, frameCount, animation.Positions, ReadPosition);
127 ReadRawArray(shortcutOffset, shortcutCount, animation.Shortcuts, ReadShortcut);
128 ReadRawArray(damageOffset, damageCount, animation.SelfDamage, ReadDamage);
129 ReadRawArray(particleOffset, particleCount, animation.Particles, ReadParticle);
130 ReadRawArray(footstepOffset, footstepCount, animation.Footsteps, ReadFootstep);
131 ReadRawArray(soundOffset, soundCount, animation.Sounds, ReadSound);
132 ReadRawArray(motionBlurOffset, motionBlurCount, animation.MotionBlur, ReadMotionBlur);
133 ReadRawArray(attackOffset, attackCount, animation.Attacks, ReadAttack);
134
135 foreach (var attack in animation.Attacks)
136 {
137 for (int i = attack.Start; i <= attack.End; i++)
138 {
139 var extent = extents.FirstOrDefault(e => e.Frame == i);
140
141 if (extent != null)
142 attack.Extents.Add(extent.Extent);
143 }
144 }
145 }
146
147 private void ReadRotations(int offset, int boneCount, int frameCount)
148 {
149 using (var raw = tram.GetRawReader(offset))
150 {
151 int basePosition = raw.Position;
152 var boneOffsets = raw.ReadUInt16Array(boneCount);
153
154 foreach (int boneOffset in boneOffsets)
155 {
156 raw.Position = basePosition + boneOffset;
157
158 var keys = new List<KeyFrame>();
159 int time = 0;
160
161 do
162 {
163 var key = new KeyFrame();
164
165 if (animation.FrameSize == 6)
166 {
167 key.Rotation.X = raw.ReadInt16() * 180.0f / 32767.5f;
168 key.Rotation.Y = raw.ReadInt16() * 180.0f / 32767.5f;
169 key.Rotation.Z = raw.ReadInt16() * 180.0f / 32767.5f;
170 }
171 else if (animation.FrameSize == 16)
172 {
173 key.Rotation = raw.ReadQuaternion().ToVector4();
174 }
175
176 if (time == frameCount - 1)
177 key.Duration = 1;
178 else
179 key.Duration = raw.ReadByte();
180
181 time += key.Duration;
182 keys.Add(key);
183
184 } while (time < frameCount);
185
186 animation.Rotations.Add(keys);
187 }
188 }
189 }
190
191 private List<DatExtent> ReadExtentInfo()
192 {
193 var info = new DatExtentInfo
194 {
195 MaxHorizontal = dat.ReadSingle(),
196 MinY = dat.ReadSingle(),
197 MaxY = dat.ReadSingle()
198 };
199
200 for (int i = 0; i < animation.AttackRing.Length; i++)
201 animation.AttackRing[i] = dat.ReadSingle();
202
203 info.FirstExtent.Frame = dat.ReadUInt16();
204 info.FirstExtent.Attack = dat.ReadByte();
205 info.FirstExtent.AttackOffset = dat.ReadByte();
206 info.FirstExtent.Location = dat.ReadVector2();
207 info.FirstExtent.Height = dat.ReadSingle();
208 info.FirstExtent.Length = dat.ReadSingle();
209 info.FirstExtent.MinY = dat.ReadSingle();
210 info.FirstExtent.MaxY = dat.ReadSingle();
211 info.FirstExtent.Angle = dat.ReadSingle();
212
213 info.MaxExtent.Frame = dat.ReadUInt16();
214 info.MaxExtent.Attack = dat.ReadByte();
215 info.MaxExtent.AttackOffset = dat.ReadByte();
216 info.MaxExtent.Location = dat.ReadVector2();
217 info.MaxExtent.Height = dat.ReadSingle();
218 info.MaxExtent.Length = dat.ReadSingle();
219 info.MaxExtent.MinY = dat.ReadSingle();
220 info.MaxExtent.MaxY = dat.ReadSingle();
221 info.MaxExtent.Angle = dat.ReadSingle();
222
223 dat.Skip(4);
224
225 int extentCount = dat.ReadInt32();
226 int extentOffset = dat.ReadInt32();
227
228 var extents = new List<DatExtent>();
229 ReadRawArray(extentOffset, extentCount, extents, ReadExtent);
230
231 foreach (var datExtent in extents)
232 {
233 var attackExtent = datExtent.Extent;
234
235 if (datExtent.Frame == info.FirstExtent.Frame)
236 {
237 attackExtent.Angle = MathHelper.ToDegrees(info.FirstExtent.Angle);
238 attackExtent.Length = info.FirstExtent.Length;
239 attackExtent.MinY = info.FirstExtent.MinY;
240 attackExtent.MaxY = info.FirstExtent.MaxY;
241 }
242 else if (datExtent.Frame == info.MaxExtent.Frame)
243 {
244 attackExtent.Angle = MathHelper.ToDegrees(info.MaxExtent.Angle);
245 attackExtent.Length = info.MaxExtent.Length;
246 attackExtent.MinY = info.MaxExtent.MinY;
247 attackExtent.MaxY = info.MaxExtent.MaxY;
248 }
249
250 if (Math.Abs(attackExtent.MinY - info.MinY) < 0.01f)
251 attackExtent.MinY = info.MinY;
252
253 if (Math.Abs(attackExtent.MaxY - info.MaxY) < 0.01f)
254 attackExtent.MaxY = info.MaxY;
255 }
256
257 return extents;
258 }
259
260 private void ReadOptionalThrowInfo()
261 {
262 int offset = dat.ReadInt32();
263
264 if (offset != 0)
265 {
266 using (var raw = tram.GetRawReader(offset))
267 animation.ThrowSource = ReadThrowInfo(raw);
268 }
269 }
270
271 private ThrowInfo ReadThrowInfo(BinaryReader raw)
272 {
273 return new ThrowInfo
274 {
275 Position = raw.ReadVector3(),
276 Angle = raw.ReadSingle(),
277 Distance = raw.ReadSingle(),
278 Type = (AnimationType)raw.ReadUInt16()
279 };
280 }
281
282 private Shortcut ReadShortcut(BinaryReader raw)
283 {
284 return new Shortcut
285 {
286 FromState = (AnimationState)raw.ReadUInt16(),
287 Length = raw.ReadUInt16(),
288 ReplaceAtomic = (raw.ReadInt32() != 0)
289 };
290 }
291
292 private Footstep ReadFootstep(BinaryReader raw)
293 {
294 return new Footstep
295 {
296 Frame = raw.ReadUInt16(),
297 Type = (FootstepType)raw.ReadUInt16()
298 };
299 }
300
301 private Sound ReadSound(BinaryReader raw)
302 {
303 return new Sound
304 {
305 Name = raw.ReadString(32),
306 Start = raw.ReadUInt16()
307 };
308 }
309
310 private MotionBlur ReadMotionBlur(BinaryReader raw)
311 {
312 var motionBlur = new MotionBlur
313 {
314 Bones = (BoneMask)raw.ReadInt32(),
315 Start = raw.ReadUInt16(),
316 End = raw.ReadUInt16(),
317 Lifetime = raw.ReadByte(),
318 Alpha = raw.ReadByte(),
319 Interval = raw.ReadByte()
320 };
321
322 raw.Skip(1);
323
324 return motionBlur;
325 }
326
327 private Particle ReadParticle(BinaryReader raw)
328 {
329 return new Particle
330 {
331 Start = raw.ReadUInt16(),
332 End = raw.ReadUInt16(),
333 Bone = (Bone)raw.ReadInt32(),
334 Name = raw.ReadString(16)
335 };
336 }
337
338 private Damage ReadDamage(BinaryReader raw)
339 {
340 return new Damage
341 {
342 Points = raw.ReadUInt16(),
343 Frame = raw.ReadUInt16()
344 };
345 }
346
347 private Position ReadPosition(BinaryReader raw)
348 {
349 return new Position
350 {
351 X = raw.ReadInt16() * 0.01f,
352 Z = raw.ReadInt16() * 0.01f,
353 Height = raw.ReadUInt16() * 0.01f,
354 YOffset = raw.ReadInt16() * 0.01f
355 };
356 }
357
358 private Attack ReadAttack(BinaryReader raw)
359 {
360 var attack = new Attack
361 {
362 Bones = (BoneMask)raw.ReadInt32(),
363 Knockback = raw.ReadSingle(),
364 Flags = (AttackFlags)raw.ReadInt32(),
365 HitPoints = raw.ReadInt16(),
366 Start = raw.ReadUInt16(),
367 End = raw.ReadUInt16(),
368 HitType = (AnimationType)raw.ReadUInt16(),
369 HitLength = raw.ReadUInt16(),
370 StunLength = raw.ReadUInt16(),
371 StaggerLength = raw.ReadUInt16()
372 };
373
374 raw.Skip(6);
375
376 return attack;
377 }
378
379 private DatExtent ReadExtent(BinaryReader raw)
380 {
381 var extent = new DatExtent();
382 extent.Frame = raw.ReadInt16();
383 extent.Extent.Angle = raw.ReadUInt16() * 360.0f / 65535.0f;
384 extent.Extent.Length = (raw.ReadUInt32() & 0xffffu) * 0.01f;
385 extent.Extent.MinY = raw.ReadInt16() * 0.01f;
386 extent.Extent.MaxY = raw.ReadInt16() * 0.01f;
387 return extent;
388 }
389
390 private void ReadRawArray<T>(int offset, int count, List<T> list, Func<BinaryReader, T> readElement)
391 {
392 if (offset == 0 || count == 0)
393 return;
394
395 using (var raw = tram.GetRawReader(offset))
396 {
397 for (int i = 0; i < count; i++)
398 list.Add(readElement(raw));
399 }
400 }
401 }
402}
Note: See TracBrowser for help on using the repository browser.