[1114] | 1 | using System;
|
---|
| 2 | using System.Collections.Generic;
|
---|
| 3 |
|
---|
| 4 | namespace 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 | }
|
---|