| 1 | using System; | 
 
 
 
 
 | 2 | using System.Collections.Generic; | 
 
 
 
 
 | 3 | using System.IO; | 
 
 
 
 
 | 4 | using System.Xml; | 
 
 
 
 
 | 5 | using Oni.Metadata; | 
 
 
 
 
 | 6 | using Oni.Xml; | 
 
 
 
 
 | 7 |  | 
 
 
 
 
 | 8 | namespace Oni.Totoro | 
 
 
 
 
 | 9 | { | 
 
 
 
 
 | 10 | internal class AnimationXmlReader | 
 
 
 
 
 | 11 | { | 
 
 
 
 
 | 12 | private const string ns = ""; | 
 
 
 
 
 | 13 | private static readonly char[] emptyChars = new char[0]; | 
 
 
 
 
 | 14 | private XmlReader xml; | 
 
 
 
 
 | 15 | private string basePath; | 
 
 
 
 
 | 16 | private Animation animation; | 
 
 
 
 
 | 17 | private AnimationDaeReader daeReader; | 
 
 
 
 
 | 18 |  | 
 
 
 
 
 | 19 | private AnimationXmlReader() | 
 
 
 
 
 | 20 | { | 
 
 
 
 
 | 21 | } | 
 
 
 
 
 | 22 |  | 
 
 
 
 
 | 23 | public static Animation Read(XmlReader xml, string baseDir) | 
 
 
 
 
 | 24 | { | 
 
 
 
 
 | 25 | var reader = new AnimationXmlReader | 
 
 
 
 
 | 26 | { | 
 
 
 
 
 | 27 | xml = xml, | 
 
 
 
 
 | 28 | basePath = baseDir, | 
 
 
 
 
 | 29 | animation = new Animation() | 
 
 
 
 
 | 30 | }; | 
 
 
 
 
 | 31 |  | 
 
 
 
 
 | 32 | var animation = reader.Read(); | 
 
 
 
 
 | 33 | animation.ValidateFrames(); | 
 
 
 
 
 | 34 | return animation; | 
 
 
 
 
 | 35 | } | 
 
 
 
 
 | 36 |  | 
 
 
 
 
 | 37 | private Animation Read() | 
 
 
 
 
 | 38 | { | 
 
 
 
 
 | 39 | animation.Name = xml.GetAttribute("Name"); | 
 
 
 
 
 | 40 | xml.ReadStartElement("Animation", ns); | 
 
 
 
 
 | 41 |  | 
 
 
 
 
 | 42 | if (xml.IsStartElement("DaeImport") || xml.IsStartElement("Import")) | 
 
 
 
 
 | 43 | ImportDaeAnimation(); | 
 
 
 
 
 | 44 |  | 
 
 
 
 
 | 45 | xml.ReadStartElement("Lookup"); | 
 
 
 
 
 | 46 | animation.Type = MetaEnum.Parse<AnimationType>(xml.ReadElementContentAsString("Type", ns)); | 
 
 
 
 
 | 47 | animation.AimingType = MetaEnum.Parse<AnimationType>(xml.ReadElementContentAsString("AimingType", ns)); | 
 
 
 
 
 | 48 | animation.FromState = MetaEnum.Parse<AnimationState>(xml.ReadElementContentAsString("FromState", ns)); | 
 
 
 
 
 | 49 | animation.ToState = MetaEnum.Parse<AnimationState>(xml.ReadElementContentAsString("ToState", ns)); | 
 
 
 
 
 | 50 | animation.Varient = MetaEnum.Parse<AnimationVarient>(xml.ReadElementContentAsString("Varient", ns)); | 
 
 
 
 
 | 51 | animation.FirstLevelAvailable = xml.ReadElementContentAsInt("FirstLevel", ns); | 
 
 
 
 
 | 52 | ReadRawArray("Shortcuts", animation.Shortcuts, Read); | 
 
 
 
 
 | 53 | xml.ReadEndElement(); | 
 
 
 
 
 | 54 |  | 
 
 
 
 
 | 55 | animation.Flags = MetaEnum.Parse<AnimationFlags>(xml.ReadElementContentAsString("Flags", ns)); | 
 
 
 
 
 | 56 | xml.ReadStartElement("Atomic", ns); | 
 
 
 
 
 | 57 | animation.AtomicStart = xml.ReadElementContentAsInt("Start", ns); | 
 
 
 
 
 | 58 | animation.AtomicEnd = xml.ReadElementContentAsInt("End", ns); | 
 
 
 
 
 | 59 | xml.ReadEndElement(); | 
 
 
 
 
 | 60 | xml.ReadStartElement("Invulnerable", ns); | 
 
 
 
 
 | 61 | animation.InvulnerableStart = xml.ReadElementContentAsInt("Start", ns); | 
 
 
 
 
 | 62 | animation.InvulnerableEnd = xml.ReadElementContentAsInt("End", ns); | 
 
 
 
 
 | 63 | xml.ReadEndElement(); | 
 
 
 
 
 | 64 | xml.ReadStartElement("Overlay", ns); | 
 
 
 
 
 | 65 | animation.OverlayUsedBones = MetaEnum.Parse<BoneMask>(xml.ReadElementContentAsString("UsedBones", ns)); | 
 
 
 
 
 | 66 | animation.OverlayReplacedBones = MetaEnum.Parse<BoneMask>(xml.ReadElementContentAsString("ReplacedBones", ns)); | 
 
 
 
 
 | 67 | xml.ReadEndElement(); | 
 
 
 
 
 | 68 |  | 
 
 
 
 
 | 69 | xml.ReadStartElement("DirectAnimations", ns); | 
 
 
 
 
 | 70 | animation.DirectAnimations[0] = xml.ReadElementContentAsString("Link", ns); | 
 
 
 
 
 | 71 | animation.DirectAnimations[1] = xml.ReadElementContentAsString("Link", ns); | 
 
 
 
 
 | 72 | xml.ReadEndElement(); | 
 
 
 
 
 | 73 | xml.ReadStartElement("Pause"); | 
 
 
 
 
 | 74 | animation.HardPause = xml.ReadElementContentAsInt("Hard", ns); | 
 
 
 
 
 | 75 | animation.SoftPause = xml.ReadElementContentAsInt("Soft", ns); | 
 
 
 
 
 | 76 | xml.ReadEndElement(); | 
 
 
 
 
 | 77 | xml.ReadStartElement("Interpolation", ns); | 
 
 
 
 
 | 78 | animation.InterpolationEnd = xml.ReadElementContentAsInt("End", ns); | 
 
 
 
 
 | 79 | animation.InterpolationMax = xml.ReadElementContentAsInt("Max", ns); | 
 
 
 
 
 | 80 | xml.ReadEndElement(); | 
 
 
 
 
 | 81 |  | 
 
 
 
 
 | 82 | animation.FinalRotation = MathHelper.ToRadians(xml.ReadElementContentAsFloat("FinalRotation", ns)); | 
 
 
 
 
 | 83 | animation.Direction = MetaEnum.Parse<Direction>(xml.ReadElementContentAsString("Direction", ns)); | 
 
 
 
 
 | 84 | animation.Vocalization = xml.ReadElementContentAsInt("Vocalization", ns); | 
 
 
 
 
 | 85 | animation.ActionFrame = xml.ReadElementContentAsInt("ActionFrame", ns); | 
 
 
 
 
 | 86 | animation.Impact = xml.ReadElementContentAsString("Impact", ns); | 
 
 
 
 
 | 87 |  | 
 
 
 
 
 | 88 | ReadRawArray("Particle", animation.Particles, Read); | 
 
 
 
 
 | 89 | ReadRawArray("MotionBlur", animation.MotionBlur, Read); | 
 
 
 
 
 | 90 | ReadRawArray("Footsteps", animation.Footsteps, Read); | 
 
 
 
 
 | 91 | ReadRawArray("Sounds", animation.Sounds, Read); | 
 
 
 
 
 | 92 |  | 
 
 
 
 
 | 93 | if (daeReader == null) | 
 
 
 
 
 | 94 | { | 
 
 
 
 
 | 95 | ReadHeights(); | 
 
 
 
 
 | 96 | ReadVelocities(); | 
 
 
 
 
 | 97 | ReadRotations(); | 
 
 
 
 
 | 98 | ReadPositions(); | 
 
 
 
 
 | 99 | } | 
 
 
 
 
 | 100 |  | 
 
 
 
 
 | 101 | ReadThrowInfo(); | 
 
 
 
 
 | 102 | ReadRawArray("SelfDamage", animation.SelfDamage, Read); | 
 
 
 
 
 | 103 |  | 
 
 
 
 
 | 104 | if (xml.IsStartElement("Attacks")) | 
 
 
 
 
 | 105 | { | 
 
 
 
 
 | 106 | ReadRawArray("Attacks", animation.Attacks, Read); | 
 
 
 
 
 | 107 | ReadAttackRing(); | 
 
 
 
 
 | 108 | } | 
 
 
 
 
 | 109 |  | 
 
 
 
 
 | 110 | xml.ReadEndElement(); | 
 
 
 
 
 | 111 |  | 
 
 
 
 
 | 112 | if (daeReader != null) | 
 
 
 
 
 | 113 | { | 
 
 
 
 
 | 114 | daeReader.Read(animation); | 
 
 
 
 
 | 115 | } | 
 
 
 
 
 | 116 |  | 
 
 
 
 
 | 117 | return animation; | 
 
 
 
 
 | 118 | } | 
 
 
 
 
 | 119 |  | 
 
 
 
 
 | 120 | private void ReadVelocities() | 
 
 
 
 
 | 121 | { | 
 
 
 
 
 | 122 | if (!xml.IsStartElement("Velocities")) | 
 
 
 
 
 | 123 | return; | 
 
 
 
 
 | 124 |  | 
 
 
 
 
 | 125 | if (xml.SkipEmpty()) | 
 
 
 
 
 | 126 | return; | 
 
 
 
 
 | 127 |  | 
 
 
 
 
 | 128 | xml.ReadStartElement(); | 
 
 
 
 
 | 129 |  | 
 
 
 
 
 | 130 | while (xml.IsStartElement()) | 
 
 
 
 
 | 131 | animation.Velocities.Add(xml.ReadElementContentAsVector2()); | 
 
 
 
 
 | 132 |  | 
 
 
 
 
 | 133 | xml.ReadEndElement(); | 
 
 
 
 
 | 134 | } | 
 
 
 
 
 | 135 |  | 
 
 
 
 
 | 136 | private void ReadPositions() | 
 
 
 
 
 | 137 | { | 
 
 
 
 
 | 138 | var xz = new Vector2(); | 
 
 
 
 
 | 139 |  | 
 
 
 
 
 | 140 | if (xml.IsStartElement("PositionOffset")) | 
 
 
 
 
 | 141 | { | 
 
 
 
 
 | 142 | xml.ReadStartElement(); | 
 
 
 
 
 | 143 | xz.X = xml.ReadElementContentAsFloat("X", ns); | 
 
 
 
 
 | 144 | xz.Y = xml.ReadElementContentAsFloat("Z", ns); | 
 
 
 
 
 | 145 | xml.ReadEndElement(); | 
 
 
 
 
 | 146 | } | 
 
 
 
 
 | 147 |  | 
 
 
 
 
 | 148 | ReadRawArray("Positions", animation.Positions, ReadPosition); | 
 
 
 
 
 | 149 |  | 
 
 
 
 
 | 150 | for (int i = 0; i < animation.Positions.Count; i++) | 
 
 
 
 
 | 151 | { | 
 
 
 
 
 | 152 | var position = animation.Positions[i]; | 
 
 
 
 
 | 153 | position.X = xz.X; | 
 
 
 
 
 | 154 | position.Z = xz.Y; | 
 
 
 
 
 | 155 | xz += animation.Velocities[i]; | 
 
 
 
 
 | 156 | } | 
 
 
 
 
 | 157 | } | 
 
 
 
 
 | 158 |  | 
 
 
 
 
 | 159 | private void ReadRotations() | 
 
 
 
 
 | 160 | { | 
 
 
 
 
 | 161 | var rotations = animation.Rotations; | 
 
 
 
 
 | 162 |  | 
 
 
 
 
 | 163 | xml.ReadStartElement("Rotations"); | 
 
 
 
 
 | 164 |  | 
 
 
 
 
 | 165 | while (xml.IsStartElement()) | 
 
 
 
 
 | 166 | { | 
 
 
 
 
 | 167 | xml.ReadStartElement("Bone"); | 
 
 
 
 
 | 168 |  | 
 
 
 
 
 | 169 | var keys = new List<KeyFrame>(); | 
 
 
 
 
 | 170 |  | 
 
 
 
 
 | 171 | int count = 0; | 
 
 
 
 
 | 172 |  | 
 
 
 
 
 | 173 | while (xml.IsStartElement()) | 
 
 
 
 
 | 174 | { | 
 
 
 
 
 | 175 | string name = xml.LocalName; | 
 
 
 
 
 | 176 | string[] tokens = xml.ReadElementContentAsString().Split(emptyChars, StringSplitOptions.RemoveEmptyEntries); | 
 
 
 
 
 | 177 |  | 
 
 
 
 
 | 178 | var key = new KeyFrame(); | 
 
 
 
 
 | 179 | key.Duration = XmlConvert.ToByte(tokens[0]); | 
 
 
 
 
 | 180 |  | 
 
 
 
 
 | 181 | switch (name) | 
 
 
 
 
 | 182 | { | 
 
 
 
 
 | 183 | case "EKey": | 
 
 
 
 
 | 184 | animation.FrameSize = 6; | 
 
 
 
 
 | 185 | key.Rotation.X = XmlConvert.ToSingle(tokens[1]); | 
 
 
 
 
 | 186 | key.Rotation.Y = XmlConvert.ToSingle(tokens[2]); | 
 
 
 
 
 | 187 | key.Rotation.Z = XmlConvert.ToSingle(tokens[3]); | 
 
 
 
 
 | 188 | break; | 
 
 
 
 
 | 189 |  | 
 
 
 
 
 | 190 | case "QKey": | 
 
 
 
 
 | 191 | animation.FrameSize = 16; | 
 
 
 
 
 | 192 | key.Rotation.X = XmlConvert.ToSingle(tokens[1]); | 
 
 
 
 
 | 193 | key.Rotation.Y = XmlConvert.ToSingle(tokens[2]); | 
 
 
 
 
 | 194 | key.Rotation.Z = XmlConvert.ToSingle(tokens[3]); | 
 
 
 
 
 | 195 | key.Rotation.W = -XmlConvert.ToSingle(tokens[4]); | 
 
 
 
 
 | 196 | break; | 
 
 
 
 
 | 197 |  | 
 
 
 
 
 | 198 | default: | 
 
 
 
 
 | 199 | throw new InvalidDataException(string.Format("Unknonw animation key type '{0}'", name)); | 
 
 
 
 
 | 200 | } | 
 
 
 
 
 | 201 |  | 
 
 
 
 
 | 202 | count += key.Duration; | 
 
 
 
 
 | 203 | keys.Add(key); | 
 
 
 
 
 | 204 | } | 
 
 
 
 
 | 205 |  | 
 
 
 
 
 | 206 | if (count != animation.Velocities.Count) | 
 
 
 
 
 | 207 | throw new InvalidDataException("bad number of frames"); | 
 
 
 
 
 | 208 |  | 
 
 
 
 
 | 209 | rotations.Add(keys); | 
 
 
 
 
 | 210 | xml.ReadEndElement(); | 
 
 
 
 
 | 211 | } | 
 
 
 
 
 | 212 |  | 
 
 
 
 
 | 213 | xml.ReadEndElement(); | 
 
 
 
 
 | 214 | } | 
 
 
 
 
 | 215 |  | 
 
 
 
 
 | 216 | private void ReadHeights() | 
 
 
 
 
 | 217 | { | 
 
 
 
 
 | 218 | if (!xml.IsStartElement("Heights")) | 
 
 
 
 
 | 219 | return; | 
 
 
 
 
 | 220 |  | 
 
 
 
 
 | 221 | if (xml.SkipEmpty()) | 
 
 
 
 
 | 222 | return; | 
 
 
 
 
 | 223 |  | 
 
 
 
 
 | 224 | xml.ReadStartElement(); | 
 
 
 
 
 | 225 |  | 
 
 
 
 
 | 226 | while (xml.IsStartElement()) | 
 
 
 
 
 | 227 | animation.Heights.Add(xml.ReadElementContentAsFloat("Height", ns)); | 
 
 
 
 
 | 228 |  | 
 
 
 
 
 | 229 | xml.ReadEndElement(); | 
 
 
 
 
 | 230 | } | 
 
 
 
 
 | 231 |  | 
 
 
 
 
 | 232 | private void ReadThrowInfo() | 
 
 
 
 
 | 233 | { | 
 
 
 
 
 | 234 | if (!xml.IsStartElement("ThrowSource")) | 
 
 
 
 
 | 235 | return; | 
 
 
 
 
 | 236 |  | 
 
 
 
 
 | 237 | if (xml.SkipEmpty()) | 
 
 
 
 
 | 238 | return; | 
 
 
 
 
 | 239 |  | 
 
 
 
 
 | 240 | animation.ThrowSource = new ThrowInfo(); | 
 
 
 
 
 | 241 | xml.ReadStartElement("ThrowSource"); | 
 
 
 
 
 | 242 | xml.ReadStartElement("TargetAdjustment"); | 
 
 
 
 
 | 243 | animation.ThrowSource.Position = xml.ReadElementContentAsVector3("Position"); | 
 
 
 
 
 | 244 | animation.ThrowSource.Angle = xml.ReadElementContentAsFloat("Angle", ns); | 
 
 
 
 
 | 245 | xml.ReadEndElement(); | 
 
 
 
 
 | 246 | animation.ThrowSource.Distance = xml.ReadElementContentAsFloat("Distance", ns); | 
 
 
 
 
 | 247 | animation.ThrowSource.Type = MetaEnum.Parse<AnimationType>(xml.ReadElementContentAsString("TargetType", ns)); | 
 
 
 
 
 | 248 | xml.ReadEndElement(); | 
 
 
 
 
 | 249 | } | 
 
 
 
 
 | 250 |  | 
 
 
 
 
 | 251 | private void ReadAttackRing() | 
 
 
 
 
 | 252 | { | 
 
 
 
 
 | 253 | if (!xml.IsStartElement("AttackRing") && !xml.IsStartElement("HorizontalExtents")) | 
 
 
 
 
 | 254 | return; | 
 
 
 
 
 | 255 |  | 
 
 
 
 
 | 256 | if (animation.Attacks.Count == 0) | 
 
 
 
 
 | 257 | { | 
 
 
 
 
 | 258 | Console.Error.WriteLine("Warning: AttackRing found but no attacks are present, ignoring"); | 
 
 
 
 
 | 259 | xml.Skip(); | 
 
 
 
 
 | 260 | return; | 
 
 
 
 
 | 261 | } | 
 
 
 
 
 | 262 |  | 
 
 
 
 
 | 263 | xml.ReadStartElement(); | 
 
 
 
 
 | 264 |  | 
 
 
 
 
 | 265 | for (int i = 0; i < 36; i++) | 
 
 
 
 
 | 266 | animation.AttackRing[i] = xml.ReadElementContentAsFloat(); | 
 
 
 
 
 | 267 |  | 
 
 
 
 
 | 268 | xml.ReadEndElement(); | 
 
 
 
 
 | 269 | } | 
 
 
 
 
 | 270 |  | 
 
 
 
 
 | 271 | private void ReadPosition(Position position) | 
 
 
 
 
 | 272 | { | 
 
 
 
 
 | 273 | xml.ReadStartElement("Position"); | 
 
 
 
 
 | 274 | position.Height = xml.ReadElementContentAsFloat("Height", ns); | 
 
 
 
 
 | 275 | position.YOffset = xml.ReadElementContentAsFloat("YOffset", ns); | 
 
 
 
 
 | 276 | xml.ReadEndElement(); | 
 
 
 
 
 | 277 | } | 
 
 
 
 
 | 278 |  | 
 
 
 
 
 | 279 | private void Read(Particle particle) | 
 
 
 
 
 | 280 | { | 
 
 
 
 
 | 281 | xml.ReadStartElement("Particle"); | 
 
 
 
 
 | 282 | particle.Start = xml.ReadElementContentAsInt("Start", ns); | 
 
 
 
 
 | 283 | particle.End = xml.ReadElementContentAsInt("End", ns); | 
 
 
 
 
 | 284 | particle.Bone = MetaEnum.Parse<Bone>(xml.ReadElementContentAsString("Bone", ns)); | 
 
 
 
 
 | 285 | particle.Name = xml.ReadElementContentAsString("Name", ns); | 
 
 
 
 
 | 286 | xml.ReadEndElement(); | 
 
 
 
 
 | 287 | } | 
 
 
 
 
 | 288 |  | 
 
 
 
 
 | 289 | private void Read(Sound sound) | 
 
 
 
 
 | 290 | { | 
 
 
 
 
 | 291 | xml.ReadStartElement("Sound"); | 
 
 
 
 
 | 292 | sound.Name = xml.ReadElementContentAsString("Name", ns); | 
 
 
 
 
 | 293 | sound.Start = xml.ReadElementContentAsInt("Start", ns); | 
 
 
 
 
 | 294 | xml.ReadEndElement(); | 
 
 
 
 
 | 295 | } | 
 
 
 
 
 | 296 |  | 
 
 
 
 
 | 297 | private void Read(Shortcut shortcut) | 
 
 
 
 
 | 298 | { | 
 
 
 
 
 | 299 | xml.ReadStartElement("Shortcut"); | 
 
 
 
 
 | 300 | shortcut.FromState = MetaEnum.Parse<AnimationState>(xml.ReadElementContentAsString("FromState", ns)); | 
 
 
 
 
 | 301 | shortcut.Length = xml.ReadElementContentAsInt("Length", ns); | 
 
 
 
 
 | 302 | shortcut.ReplaceAtomic = (xml.ReadElementContentAsString("ReplaceAtomic", ns) == "yes"); | 
 
 
 
 
 | 303 | xml.ReadEndElement(); | 
 
 
 
 
 | 304 | } | 
 
 
 
 
 | 305 |  | 
 
 
 
 
 | 306 | private void Read(Footstep footstep) | 
 
 
 
 
 | 307 | { | 
 
 
 
 
 | 308 | xml.ReadStartElement("Footstep"); | 
 
 
 
 
 | 309 |  | 
 
 
 
 
 | 310 | string frame = xml.GetAttribute("Frame"); | 
 
 
 
 
 | 311 |  | 
 
 
 
 
 | 312 | if (frame != null) | 
 
 
 
 
 | 313 | { | 
 
 
 
 
 | 314 | footstep.Frame = XmlConvert.ToInt32(frame); | 
 
 
 
 
 | 315 | footstep.Type = MetaEnum.Parse<FootstepType>(xml.GetAttribute("Type")); | 
 
 
 
 
 | 316 | } | 
 
 
 
 
 | 317 | else | 
 
 
 
 
 | 318 | { | 
 
 
 
 
 | 319 | footstep.Frame = xml.ReadElementContentAsInt("Frame", ns); | 
 
 
 
 
 | 320 | footstep.Type = MetaEnum.Parse<FootstepType>(xml.ReadElementContentAsString("Type", ns)); | 
 
 
 
 
 | 321 | } | 
 
 
 
 
 | 322 |  | 
 
 
 
 
 | 323 | xml.ReadEndElement(); | 
 
 
 
 
 | 324 | } | 
 
 
 
 
 | 325 |  | 
 
 
 
 
 | 326 | private void Read(Damage damage) | 
 
 
 
 
 | 327 | { | 
 
 
 
 
 | 328 | xml.ReadStartElement("Damage"); | 
 
 
 
 
 | 329 | damage.Points = xml.ReadElementContentAsInt("Points", ns); | 
 
 
 
 
 | 330 | damage.Frame = xml.ReadElementContentAsInt("Frame", ns); | 
 
 
 
 
 | 331 | xml.ReadEndElement(); | 
 
 
 
 
 | 332 | } | 
 
 
 
 
 | 333 |  | 
 
 
 
 
 | 334 | private void Read(MotionBlur d) | 
 
 
 
 
 | 335 | { | 
 
 
 
 
 | 336 | xml.ReadStartElement("MotionBlur"); | 
 
 
 
 
 | 337 | d.Bones = MetaEnum.Parse<BoneMask>(xml.ReadElementContentAsString("Bones", ns)); | 
 
 
 
 
 | 338 | d.Start = xml.ReadElementContentAsInt("Start", ns); | 
 
 
 
 
 | 339 | d.End = xml.ReadElementContentAsInt("End", ns); | 
 
 
 
 
 | 340 | d.Lifetime = xml.ReadElementContentAsInt("Lifetime", ns); | 
 
 
 
 
 | 341 | d.Alpha = xml.ReadElementContentAsInt("Alpha", ns); | 
 
 
 
 
 | 342 | d.Interval = xml.ReadElementContentAsInt("Interval", ns); | 
 
 
 
 
 | 343 | xml.ReadEndElement(); | 
 
 
 
 
 | 344 | } | 
 
 
 
 
 | 345 |  | 
 
 
 
 
 | 346 | private void Read(Attack attack) | 
 
 
 
 
 | 347 | { | 
 
 
 
 
 | 348 | xml.ReadStartElement("Attack"); | 
 
 
 
 
 | 349 | attack.Start = xml.ReadElementContentAsInt("Start", ns); | 
 
 
 
 
 | 350 | attack.End = xml.ReadElementContentAsInt("End", ns); | 
 
 
 
 
 | 351 | attack.Bones = MetaEnum.Parse<BoneMask>(xml.ReadElementContentAsString("Bones", ns)); | 
 
 
 
 
 | 352 | attack.Flags = MetaEnum.Parse<AttackFlags>(xml.ReadElementContentAsString("Flags", ns)); | 
 
 
 
 
 | 353 | attack.Knockback = xml.ReadElementContentAsFloat("Knockback", ns); | 
 
 
 
 
 | 354 | attack.HitPoints = xml.ReadElementContentAsInt("HitPoints", ns); | 
 
 
 
 
 | 355 | attack.HitType = MetaEnum.Parse<AnimationType>(xml.ReadElementContentAsString("HitType", ns)); | 
 
 
 
 
 | 356 | attack.HitLength = xml.ReadElementContentAsInt("HitLength", ns); | 
 
 
 
 
 | 357 | attack.StunLength = xml.ReadElementContentAsInt("StunLength", ns); | 
 
 
 
 
 | 358 | attack.StaggerLength = xml.ReadElementContentAsInt("StaggerLength", ns); | 
 
 
 
 
 | 359 |  | 
 
 
 
 
 | 360 | if (xml.IsStartElement("Extents")) | 
 
 
 
 
 | 361 | { | 
 
 
 
 
 | 362 | ReadRawArray("Extents", attack.Extents, Read); | 
 
 
 
 
 | 363 |  | 
 
 
 
 
 | 364 | if (attack.Extents.Count != attack.End - attack.Start + 1) | 
 
 
 
 
 | 365 | Console.Error.WriteLine("Error: Attack starting at frame {0} has an incorrect number of extents ({1})", attack.Start, attack.Extents.Count); | 
 
 
 
 
 | 366 | } | 
 
 
 
 
 | 367 |  | 
 
 
 
 
 | 368 | xml.ReadEndElement(); | 
 
 
 
 
 | 369 | } | 
 
 
 
 
 | 370 |  | 
 
 
 
 
 | 371 | private void Read(AttackExtent extent) | 
 
 
 
 
 | 372 | { | 
 
 
 
 
 | 373 | xml.ReadStartElement("Extent"); | 
 
 
 
 
 | 374 | extent.Angle = xml.ReadElementContentAsFloat("Angle", ns); | 
 
 
 
 
 | 375 | extent.Length = xml.ReadElementContentAsFloat("Length", ns); | 
 
 
 
 
 | 376 | extent.MinY = xml.ReadElementContentAsFloat("MinY", ns); | 
 
 
 
 
 | 377 | extent.MaxY = xml.ReadElementContentAsFloat("MaxY", ns); | 
 
 
 
 
 | 378 | xml.ReadEndElement(); | 
 
 
 
 
 | 379 | } | 
 
 
 
 
 | 380 |  | 
 
 
 
 
 | 381 | private void ReadRawArray<T>(string name, List<T> list, Action<T> elementReader) | 
 
 
 
 
 | 382 | where T : new() | 
 
 
 
 
 | 383 | { | 
 
 
 
 
 | 384 | if (xml.SkipEmpty()) | 
 
 
 
 
 | 385 | return; | 
 
 
 
 
 | 386 |  | 
 
 
 
 
 | 387 | xml.ReadStartElement(); | 
 
 
 
 
 | 388 |  | 
 
 
 
 
 | 389 | while (xml.IsStartElement()) | 
 
 
 
 
 | 390 | { | 
 
 
 
 
 | 391 | T t = new T(); | 
 
 
 
 
 | 392 | elementReader(t); | 
 
 
 
 
 | 393 | list.Add(t); | 
 
 
 
 
 | 394 | } | 
 
 
 
 
 | 395 |  | 
 
 
 
 
 | 396 | xml.ReadEndElement(); | 
 
 
 
 
 | 397 | } | 
 
 
 
 
 | 398 |  | 
 
 
 
 
 | 399 | private void ImportDaeAnimation() | 
 
 
 
 
 | 400 | { | 
 
 
 
 
 | 401 | string filePath = xml.GetAttribute("Path"); | 
 
 
 
 
 | 402 | bool empty = xml.SkipEmpty(); | 
 
 
 
 
 | 403 |  | 
 
 
 
 
 | 404 | if (!empty) | 
 
 
 
 
 | 405 | { | 
 
 
 
 
 | 406 | xml.ReadStartElement(); | 
 
 
 
 
 | 407 |  | 
 
 
 
 
 | 408 | if (filePath == null) | 
 
 
 
 
 | 409 | filePath = xml.ReadElementContentAsString("Path", ns); | 
 
 
 
 
 | 410 | } | 
 
 
 
 
 | 411 |  | 
 
 
 
 
 | 412 | filePath = Path.Combine(basePath, filePath); | 
 
 
 
 
 | 413 |  | 
 
 
 
 
 | 414 | if (!File.Exists(filePath)) | 
 
 
 
 
 | 415 | { | 
 
 
 
 
 | 416 | Console.Error.WriteLine("Could not find animation import source file '{0}'", filePath); | 
 
 
 
 
 | 417 | return; | 
 
 
 
 
 | 418 | } | 
 
 
 
 
 | 419 |  | 
 
 
 
 
 | 420 | Console.WriteLine("Importing {0}", filePath); | 
 
 
 
 
 | 421 |  | 
 
 
 
 
 | 422 | daeReader = new AnimationDaeReader(); | 
 
 
 
 
 | 423 | daeReader.Scene = Dae.Reader.ReadFile(filePath); | 
 
 
 
 
 | 424 |  | 
 
 
 
 
 | 425 | if (!empty) | 
 
 
 
 
 | 426 | { | 
 
 
 
 
 | 427 | if (xml.IsStartElement("Start")) | 
 
 
 
 
 | 428 | daeReader.StartFrame = xml.ReadElementContentAsInt("Start", ns); | 
 
 
 
 
 | 429 |  | 
 
 
 
 
 | 430 | if (xml.IsStartElement("End")) | 
 
 
 
 
 | 431 | daeReader.EndFrame = xml.ReadElementContentAsInt("End", ns); | 
 
 
 
 
 | 432 |  | 
 
 
 
 
 | 433 | xml.ReadEndElement(); | 
 
 
 
 
 | 434 | } | 
 
 
 
 
 | 435 | } | 
 
 
 
 
 | 436 | } | 
 
 
 
 
 | 437 | } |