[1114] | 1 | using System;
|
---|
| 2 | using System.Collections.Generic;
|
---|
| 3 | using System.IO;
|
---|
| 4 | using System.Xml;
|
---|
| 5 |
|
---|
| 6 | namespace Oni.Level
|
---|
| 7 | {
|
---|
| 8 | using Akira;
|
---|
| 9 | using Metadata;
|
---|
| 10 | using Motoko;
|
---|
| 11 | using Physics;
|
---|
| 12 |
|
---|
| 13 | partial class LevelImporter
|
---|
| 14 | {
|
---|
| 15 | private List<Dae.Scene> roomScenes;
|
---|
| 16 | private PolygonMesh model;
|
---|
| 17 | private AkiraDaeReader daeReader;
|
---|
| 18 |
|
---|
| 19 | private void ReadModel(XmlReader xml, string basePath)
|
---|
| 20 | {
|
---|
| 21 | xml.ReadStartElement("Environment");
|
---|
| 22 |
|
---|
| 23 | xml.ReadStartElement("Model");
|
---|
| 24 |
|
---|
| 25 | daeReader = new AkiraDaeReader();
|
---|
| 26 | model = daeReader.Mesh;
|
---|
| 27 | level.model = model;
|
---|
| 28 |
|
---|
| 29 | info.WriteLine("Reading environment...");
|
---|
| 30 |
|
---|
| 31 | while (xml.IsStartElement())
|
---|
| 32 | {
|
---|
| 33 | switch (xml.LocalName)
|
---|
| 34 | {
|
---|
| 35 | case "Import":
|
---|
| 36 | case "Scene":
|
---|
| 37 | ImportModelScene(xml, basePath);
|
---|
| 38 | break;
|
---|
| 39 |
|
---|
| 40 | case "Object":
|
---|
| 41 | xml.Skip();
|
---|
| 42 | break;
|
---|
| 43 |
|
---|
| 44 | case "Camera":
|
---|
| 45 | ReadCamera(xml, basePath);
|
---|
| 46 | break;
|
---|
| 47 |
|
---|
| 48 | case "Texture":
|
---|
| 49 | textureImporter.ReadOptions(xml, basePath);
|
---|
| 50 | break;
|
---|
| 51 |
|
---|
| 52 | default:
|
---|
| 53 | error.WriteLine("Unknown element {0}", xml.LocalName);
|
---|
| 54 | xml.Skip();
|
---|
| 55 | break;
|
---|
| 56 | }
|
---|
| 57 | }
|
---|
| 58 |
|
---|
| 59 | info.WriteLine("Reading rooms...");
|
---|
| 60 |
|
---|
| 61 | roomScenes = new List<Dae.Scene>();
|
---|
| 62 |
|
---|
| 63 | xml.ReadEndElement();
|
---|
| 64 | xml.ReadStartElement("Rooms");
|
---|
| 65 |
|
---|
| 66 | while (xml.IsStartElement("Import"))
|
---|
| 67 | {
|
---|
| 68 | string filePath = xml.GetAttribute("Path");
|
---|
| 69 |
|
---|
| 70 | if (filePath == null)
|
---|
| 71 | filePath = xml.ReadElementContentAsString();
|
---|
| 72 | else
|
---|
| 73 | xml.Skip();
|
---|
| 74 |
|
---|
| 75 | filePath = Path.Combine(basePath, filePath);
|
---|
| 76 |
|
---|
| 77 | roomScenes.Add(LoadScene(filePath));
|
---|
| 78 | }
|
---|
| 79 |
|
---|
| 80 | xml.ReadEndElement();
|
---|
| 81 |
|
---|
| 82 | if (xml.IsStartElement("Textures"))
|
---|
| 83 | ReadTextures(xml, basePath);
|
---|
| 84 |
|
---|
| 85 | xml.ReadEndElement();
|
---|
| 86 | }
|
---|
| 87 |
|
---|
| 88 | private class NodePropertiesReader
|
---|
| 89 | {
|
---|
| 90 | private readonly string basePath;
|
---|
| 91 | private readonly TextWriter error;
|
---|
| 92 | public readonly Dictionary<string, AkiraDaeNodeProperties> properties = new Dictionary<string, AkiraDaeNodeProperties>(StringComparer.Ordinal);
|
---|
| 93 |
|
---|
| 94 | public NodePropertiesReader(string basePath, TextWriter error)
|
---|
| 95 | {
|
---|
| 96 | this.basePath = basePath;
|
---|
| 97 | this.error = error;
|
---|
| 98 | }
|
---|
| 99 |
|
---|
| 100 | public Dictionary<string, AkiraDaeNodeProperties> Properties
|
---|
| 101 | {
|
---|
| 102 | get { return properties; }
|
---|
| 103 | }
|
---|
| 104 |
|
---|
| 105 | public void ReadScene(XmlReader xml, Dae.Node scene)
|
---|
| 106 | {
|
---|
| 107 | var nodeProperties = new ObjectDaeNodeProperties();
|
---|
| 108 | properties.Add(scene.Id, nodeProperties);
|
---|
| 109 |
|
---|
| 110 | while (xml.IsStartElement())
|
---|
| 111 | {
|
---|
| 112 | switch (xml.LocalName)
|
---|
| 113 | {
|
---|
| 114 | case "GunkFlags":
|
---|
| 115 | nodeProperties.GunkFlags = xml.ReadElementContentAsEnum<GunkFlags>();
|
---|
| 116 | break;
|
---|
| 117 | case "ScriptId":
|
---|
| 118 | nodeProperties.ScriptId = xml.ReadElementContentAsInt();
|
---|
| 119 | break;
|
---|
| 120 | case "Node":
|
---|
| 121 | ReadNode(xml, scene, nodeProperties);
|
---|
| 122 | break;
|
---|
| 123 | default:
|
---|
| 124 | xml.Skip();
|
---|
| 125 | break;
|
---|
| 126 | }
|
---|
| 127 | }
|
---|
| 128 | }
|
---|
| 129 |
|
---|
| 130 | private void ReadNode(XmlReader xml, Dae.Node parentNode, ObjectDaeNodeProperties parentNodeProperties)
|
---|
| 131 | {
|
---|
| 132 | string id = xml.GetAttribute("Id");
|
---|
| 133 |
|
---|
| 134 | if (string.IsNullOrEmpty(id))
|
---|
| 135 | {
|
---|
| 136 | error.Write("Each import node must have an Id attribute");
|
---|
| 137 | xml.Skip();
|
---|
| 138 | return;
|
---|
| 139 | }
|
---|
| 140 |
|
---|
| 141 | var nodeProperties = new ObjectDaeNodeProperties {
|
---|
| 142 | GunkFlags = parentNodeProperties.GunkFlags,
|
---|
| 143 | ScriptId = parentNodeProperties.ScriptId,
|
---|
| 144 | HasPhysics = parentNodeProperties.HasPhysics
|
---|
| 145 | };
|
---|
| 146 |
|
---|
| 147 | properties.Add(id, nodeProperties);
|
---|
| 148 |
|
---|
| 149 | xml.ReadStartElement("Node");
|
---|
| 150 |
|
---|
| 151 | while (xml.IsStartElement())
|
---|
| 152 | {
|
---|
| 153 | switch (xml.LocalName)
|
---|
| 154 | {
|
---|
| 155 | case "GunkFlags":
|
---|
| 156 | nodeProperties.GunkFlags |= xml.ReadElementContentAsEnum<GunkFlags>();
|
---|
| 157 | break;
|
---|
| 158 | case "ScriptId":
|
---|
| 159 | nodeProperties.ScriptId = xml.ReadElementContentAsInt();
|
---|
| 160 | break;
|
---|
| 161 | case "Physics":
|
---|
| 162 | nodeProperties.PhysicsType = xml.ReadElementContentAsEnum<ObjectPhysicsType>();
|
---|
| 163 | nodeProperties.HasPhysics = true;
|
---|
| 164 | break;
|
---|
| 165 | case "ObjectFlags":
|
---|
| 166 | nodeProperties.ObjectFlags = xml.ReadElementContentAsEnum<ObjectSetupFlags>();
|
---|
| 167 | nodeProperties.HasPhysics = true;
|
---|
| 168 | break;
|
---|
| 169 | case "Animation":
|
---|
| 170 | nodeProperties.Animations.Add(ReadAnimationClip(xml));
|
---|
| 171 | nodeProperties.HasPhysics = true;
|
---|
| 172 | break;
|
---|
| 173 | case "Particles":
|
---|
| 174 | nodeProperties.Particles.AddRange(ReadParticles(xml, basePath));
|
---|
| 175 | nodeProperties.HasPhysics = true;
|
---|
| 176 | break;
|
---|
| 177 | default:
|
---|
| 178 | error.WriteLine("Unknown physics object element {0}", xml.LocalName);
|
---|
| 179 | xml.Skip();
|
---|
| 180 | break;
|
---|
| 181 | }
|
---|
| 182 | }
|
---|
| 183 |
|
---|
| 184 | xml.ReadEndElement();
|
---|
| 185 | }
|
---|
| 186 |
|
---|
| 187 | private ObjectAnimationClip ReadAnimationClip(XmlReader xml)
|
---|
| 188 | {
|
---|
| 189 | var animClip = new ObjectAnimationClip(xml.GetAttribute("Name"));
|
---|
| 190 |
|
---|
| 191 | if (!xml.SkipEmpty())
|
---|
| 192 | {
|
---|
| 193 | xml.ReadStartElement();
|
---|
| 194 |
|
---|
| 195 | while (xml.IsStartElement())
|
---|
| 196 | {
|
---|
| 197 | switch (xml.LocalName)
|
---|
| 198 | {
|
---|
| 199 | case "Start":
|
---|
| 200 | animClip.Start = xml.ReadElementContentAsInt();
|
---|
| 201 | break;
|
---|
| 202 | case "Stop":
|
---|
| 203 | animClip.Stop = xml.ReadElementContentAsInt();
|
---|
| 204 | break;
|
---|
| 205 | case "End":
|
---|
| 206 | animClip.End = xml.ReadElementContentAsInt();
|
---|
| 207 | break;
|
---|
| 208 | case "Flags":
|
---|
| 209 | animClip.Flags = xml.ReadElementContentAsEnum<ObjectAnimationFlags>();
|
---|
| 210 | break;
|
---|
| 211 | default:
|
---|
| 212 | error.WriteLine("Unknown object animation property {0}", xml.LocalName);
|
---|
| 213 | xml.Skip();
|
---|
| 214 | break;
|
---|
| 215 | }
|
---|
| 216 | }
|
---|
| 217 |
|
---|
| 218 | xml.ReadEndElement();
|
---|
| 219 | }
|
---|
| 220 |
|
---|
| 221 | return animClip;
|
---|
| 222 | }
|
---|
| 223 | }
|
---|
| 224 |
|
---|
| 225 | private void ImportModelScene(XmlReader xml, string basePath)
|
---|
| 226 | {
|
---|
| 227 | var filePath = Path.Combine(basePath, xml.GetAttribute("Path"));
|
---|
| 228 | var scene = LoadScene(filePath);
|
---|
| 229 |
|
---|
| 230 | var propertiesReader = new NodePropertiesReader(basePath, error);
|
---|
| 231 |
|
---|
| 232 | if (!xml.SkipEmpty())
|
---|
| 233 | {
|
---|
| 234 | xml.ReadStartElement();
|
---|
| 235 | propertiesReader.ReadScene(xml, scene);
|
---|
| 236 | xml.ReadEndElement();
|
---|
| 237 | }
|
---|
| 238 |
|
---|
| 239 | daeReader.ReadScene(scene, propertiesReader.Properties);
|
---|
| 240 |
|
---|
| 241 | if (propertiesReader.Properties.Values.Any(p => p.HasPhysics))
|
---|
| 242 | {
|
---|
| 243 | var imp = new ObjectDaeImporter(textureImporter, propertiesReader.Properties);
|
---|
| 244 |
|
---|
| 245 | imp.Import(scene);
|
---|
| 246 |
|
---|
| 247 | foreach (var node in imp.Nodes.Where(n => n.Geometries.Length > 0))
|
---|
| 248 | {
|
---|
| 249 | var setup = new ObjectSetup {
|
---|
| 250 | Name = node.Name,
|
---|
| 251 | FileName = node.FileName,
|
---|
| 252 | ScriptId = node.ScriptId,
|
---|
| 253 | Flags = node.Flags,
|
---|
| 254 | PhysicsType = ObjectPhysicsType.Animated
|
---|
| 255 | };
|
---|
| 256 |
|
---|
| 257 | setup.Geometries = node.Geometries
|
---|
| 258 | .Where(n => (n.Flags & GunkFlags.Invisible) == 0)
|
---|
| 259 | .Select(n => n.Geometry.Name).ToArray();
|
---|
| 260 |
|
---|
| 261 | foreach (var nodeGeometry in node.Geometries.Where(g => (g.Flags & GunkFlags.Invisible) == 0))
|
---|
| 262 | {
|
---|
| 263 | var writer = new DatWriter();
|
---|
| 264 | GeometryDatWriter.Write(nodeGeometry.Geometry, writer.ImporterFile);
|
---|
| 265 | writer.Write(outputDirPath);
|
---|
| 266 | }
|
---|
| 267 |
|
---|
| 268 | setup.Position = Vector3.Zero;
|
---|
| 269 | setup.Orientation = Quaternion.Identity;
|
---|
| 270 | setup.Scale = 1.0f;
|
---|
| 271 | setup.Origin = Matrix.CreateFromQuaternion(setup.Orientation)
|
---|
| 272 | * Matrix.CreateScale(setup.Scale)
|
---|
| 273 | * Matrix.CreateTranslation(setup.Position);
|
---|
| 274 |
|
---|
| 275 | //int i = 0;
|
---|
| 276 |
|
---|
| 277 | foreach (var animation in node.Animations)
|
---|
| 278 | {
|
---|
| 279 | //if (nodes.Count > 1)
|
---|
| 280 | // animation.Name += i.ToString("d2", CultureInfo.InvariantCulture);
|
---|
| 281 |
|
---|
| 282 | if ((animation.Flags & ObjectAnimationFlags.Local) == 0)
|
---|
| 283 | {
|
---|
| 284 | //animation.Scale = Matrix.CreateScale(setup.Scale);
|
---|
| 285 |
|
---|
| 286 | foreach (var key in animation.Keys)
|
---|
| 287 | {
|
---|
| 288 | key.Rotation = setup.Orientation * key.Rotation;
|
---|
| 289 | key.Translation += setup.Position;
|
---|
| 290 | }
|
---|
| 291 | }
|
---|
| 292 |
|
---|
| 293 | if ((animation.Flags & ObjectAnimationFlags.AutoStart) != 0)
|
---|
| 294 | {
|
---|
| 295 | setup.Animation = animation;
|
---|
| 296 | setup.PhysicsType = ObjectPhysicsType.Animated;
|
---|
| 297 | }
|
---|
| 298 |
|
---|
| 299 | var writer = new DatWriter();
|
---|
| 300 | writer.BeginImport();
|
---|
| 301 | ObjectDatWriter.WriteAnimation(animation, writer);
|
---|
| 302 | writer.Write(outputDirPath);
|
---|
| 303 | }
|
---|
| 304 |
|
---|
| 305 | if (setup.Animation == null && node.Animations.Length > 0)
|
---|
| 306 | {
|
---|
| 307 | setup.Animation = node.Animations[0];
|
---|
| 308 | }
|
---|
| 309 |
|
---|
| 310 | if (setup.Animation != null)
|
---|
| 311 | {
|
---|
| 312 | var frame0 = setup.Animation.Keys[0];
|
---|
| 313 |
|
---|
| 314 | setup.Scale = frame0.Scale.X;
|
---|
| 315 | setup.Orientation = frame0.Rotation;
|
---|
| 316 | setup.Position = frame0.Translation;
|
---|
| 317 | }
|
---|
| 318 |
|
---|
| 319 | level.physics.Add(setup);
|
---|
| 320 | }
|
---|
| 321 | }
|
---|
| 322 | }
|
---|
| 323 |
|
---|
| 324 | private void ImportModel(string basePath)
|
---|
| 325 | {
|
---|
| 326 | info.WriteLine("Importing objects...");
|
---|
| 327 | ImportGunkObjects();
|
---|
| 328 |
|
---|
| 329 | info.WriteLine("Importing textures...");
|
---|
| 330 | ImportModelTextures();
|
---|
| 331 |
|
---|
| 332 | info.WriteLine("Generating grids...");
|
---|
| 333 |
|
---|
| 334 | string gridFilePath = Path.Combine(basePath, string.Format("temp/grids/{0}_grids.dae", level.name));
|
---|
| 335 |
|
---|
| 336 | var gridBuilder = new RoomGridBuilder(roomScenes[0], model);
|
---|
| 337 | gridBuilder.Build();
|
---|
| 338 | AkiraDaeWriter.WriteRooms(gridBuilder.Mesh, gridFilePath);
|
---|
| 339 |
|
---|
| 340 | daeReader.ReadScene(Dae.Reader.ReadFile(gridFilePath), new Dictionary<string, AkiraDaeNodeProperties>());
|
---|
| 341 |
|
---|
| 342 | info.WriteLine("Writing environment...");
|
---|
| 343 |
|
---|
| 344 | var writer = new DatWriter();
|
---|
| 345 | AkiraDatWriter.Write(model, writer, level.name, debug);
|
---|
| 346 | writer.Write(outputDirPath);
|
---|
| 347 | }
|
---|
| 348 |
|
---|
| 349 | private void ImportGunkNode(int gunkId, Matrix transform, GunkFlags flags, Geometry geometry)
|
---|
| 350 | {
|
---|
| 351 | ImportGunk(gunkId, transform, flags, geometry, null);
|
---|
| 352 | }
|
---|
| 353 |
|
---|
| 354 | private void ImportGunk(int gunkId, Matrix transform, GunkFlags flags, Geometry geometry, string textureName)
|
---|
| 355 | {
|
---|
| 356 | TextureFormat? textureFormat = null;
|
---|
| 357 |
|
---|
| 358 | if (geometry.Texture != null)
|
---|
| 359 | {
|
---|
| 360 | Texture texture = null;
|
---|
| 361 |
|
---|
| 362 | if (!geometry.Texture.IsPlaceholder)
|
---|
| 363 | {
|
---|
| 364 | texture = TextureDatReader.ReadInfo(geometry.Texture);
|
---|
| 365 | }
|
---|
| 366 | else
|
---|
| 367 | {
|
---|
| 368 | var txmp = FindSharedInstance(TemplateTag.TXMP, geometry.Texture.Name);
|
---|
| 369 |
|
---|
| 370 | if (txmp != null)
|
---|
| 371 | texture = TextureDatReader.ReadInfo(txmp);
|
---|
| 372 | }
|
---|
| 373 |
|
---|
| 374 | if (texture != null)
|
---|
| 375 | textureFormat = texture.Format;
|
---|
| 376 | }
|
---|
| 377 | else
|
---|
| 378 | {
|
---|
| 379 | if (geometry.TextureName != null)
|
---|
| 380 | {
|
---|
| 381 | var options = textureImporter.GetOptions(geometry.TextureName, false);
|
---|
| 382 |
|
---|
| 383 | if (options != null)
|
---|
| 384 | textureFormat = options.Format;
|
---|
| 385 | }
|
---|
| 386 | }
|
---|
| 387 |
|
---|
| 388 | switch (textureFormat)
|
---|
| 389 | {
|
---|
| 390 | case TextureFormat.BGRA4444:
|
---|
| 391 | case TextureFormat.BGRA5551:
|
---|
| 392 | case TextureFormat.RGBA:
|
---|
| 393 | flags |= GunkFlags.Transparent | GunkFlags.TwoSided | GunkFlags.NoOcclusion;
|
---|
| 394 | break;
|
---|
| 395 | }
|
---|
| 396 |
|
---|
| 397 | Material material;
|
---|
| 398 |
|
---|
| 399 | if (!string.IsNullOrEmpty(textureName))
|
---|
| 400 | material = model.Materials.GetMaterial(textureName);
|
---|
| 401 | else if (!string.IsNullOrEmpty(geometry.TextureName))
|
---|
| 402 | material = model.Materials.GetMaterial(geometry.TextureName);
|
---|
| 403 | else if (geometry.Texture != null)
|
---|
| 404 | material = model.Materials.GetMaterial(geometry.Texture.Name);
|
---|
| 405 | else
|
---|
| 406 | material = model.Materials.GetMaterial("NONE");
|
---|
| 407 |
|
---|
| 408 | int pointIndexBase = model.Points.Count;
|
---|
| 409 | int texCoordIndexBase = model.TexCoords.Count;
|
---|
| 410 |
|
---|
| 411 | model.Points.AddRange(Vector3.Transform(geometry.Points, ref transform));
|
---|
| 412 | model.TexCoords.AddRange(geometry.TexCoords);
|
---|
| 413 |
|
---|
| 414 | foreach (var quad in Quadify.Do(geometry))
|
---|
| 415 | {
|
---|
| 416 | var pointIndices = new int[quad.Length];
|
---|
| 417 | var texCoordIndices = new int[quad.Length];
|
---|
| 418 | var colors = new Imaging.Color[quad.Length];
|
---|
| 419 |
|
---|
| 420 | for (int j = 0; j < quad.Length; j++)
|
---|
| 421 | {
|
---|
| 422 | pointIndices[j] = pointIndexBase + quad[j];
|
---|
| 423 | texCoordIndices[j] = texCoordIndexBase + quad[j];
|
---|
| 424 | colors[j] = new Imaging.Color(207, 207, 207);
|
---|
| 425 | }
|
---|
| 426 |
|
---|
| 427 | var poly = new Polygon(model, pointIndices) {
|
---|
| 428 | TexCoordIndices = texCoordIndices,
|
---|
| 429 | Colors = colors,
|
---|
| 430 | Material = material,
|
---|
| 431 | ObjectId = gunkId & 0xffffff,
|
---|
| 432 | ObjectType = gunkId >> 24
|
---|
| 433 | };
|
---|
| 434 |
|
---|
| 435 | poly.Flags |= flags;
|
---|
| 436 | model.Polygons.Add(poly);
|
---|
| 437 | }
|
---|
| 438 | }
|
---|
| 439 |
|
---|
| 440 | private void ImportModelTextures()
|
---|
| 441 | {
|
---|
| 442 | int imported = 0;
|
---|
| 443 | int copied = 0;
|
---|
| 444 |
|
---|
| 445 | var copy = new List<InstanceDescriptor>();
|
---|
| 446 |
|
---|
| 447 | foreach (var material in model.Polygons.Select(p => p.Material).Distinct())
|
---|
| 448 | {
|
---|
| 449 | //if (material.IsMarker)
|
---|
| 450 | // continue;
|
---|
| 451 |
|
---|
| 452 | if (File.Exists(material.ImageFilePath))
|
---|
| 453 | {
|
---|
| 454 | var options = textureImporter.AddMaterial(material);
|
---|
| 455 |
|
---|
| 456 | if (options != null)
|
---|
| 457 | material.Flags |= options.GunkFlags;
|
---|
| 458 |
|
---|
| 459 | imported++;
|
---|
| 460 | }
|
---|
| 461 | else
|
---|
| 462 | {
|
---|
| 463 | var txmp = FindSharedInstance(TemplateTag.TXMP, material.Name);
|
---|
| 464 |
|
---|
| 465 | if (txmp != null)
|
---|
| 466 | copy.Add(txmp);
|
---|
| 467 | }
|
---|
| 468 | }
|
---|
| 469 |
|
---|
| 470 | Parallel.ForEach(copy, txmp => {
|
---|
| 471 | var texture = TextureDatReader.Read(txmp);
|
---|
| 472 |
|
---|
| 473 | if ((texture.Flags & TextureFlags.HasMipMaps) == 0)
|
---|
| 474 | {
|
---|
| 475 | texture.GenerateMipMaps();
|
---|
| 476 | TextureDatWriter.Write(texture, outputDirPath);
|
---|
| 477 | System.Threading.Interlocked.Increment(ref imported);
|
---|
| 478 | }
|
---|
| 479 | else
|
---|
| 480 | {
|
---|
| 481 | string sourceFilePath = txmp.File.FilePath;
|
---|
| 482 | File.Copy(sourceFilePath, Path.Combine(outputDirPath, Path.GetFileName(sourceFilePath)), true);
|
---|
| 483 | System.Threading.Interlocked.Increment(ref copied);
|
---|
| 484 | }
|
---|
| 485 | });
|
---|
| 486 |
|
---|
| 487 | error.WriteLine("Imported {0} textures, copied {1} textures", imported, copied);
|
---|
| 488 | }
|
---|
| 489 |
|
---|
| 490 | private ObjectAnimationClip ReadAnimationClip(XmlReader xml)
|
---|
| 491 | {
|
---|
| 492 | var anim = new ObjectAnimationClip(xml.GetAttribute("Name"));
|
---|
| 493 |
|
---|
| 494 | if (!xml.SkipEmpty())
|
---|
| 495 | {
|
---|
| 496 | xml.ReadStartElement();
|
---|
| 497 |
|
---|
| 498 | while (xml.IsStartElement())
|
---|
| 499 | {
|
---|
| 500 | switch (xml.LocalName)
|
---|
| 501 | {
|
---|
| 502 | case "Start":
|
---|
| 503 | anim.Start = xml.ReadElementContentAsInt();
|
---|
| 504 | break;
|
---|
| 505 | case "Stop":
|
---|
| 506 | anim.Stop = xml.ReadElementContentAsInt();
|
---|
| 507 | break;
|
---|
| 508 | case "End":
|
---|
| 509 | anim.End = xml.ReadElementContentAsInt();
|
---|
| 510 | break;
|
---|
| 511 | case "Flags":
|
---|
| 512 | anim.Flags = xml.ReadElementContentAsEnum<ObjectAnimationFlags>();
|
---|
| 513 | break;
|
---|
| 514 | default:
|
---|
| 515 | error.WriteLine("Unknown object animation parameter {0}", xml.LocalName);
|
---|
| 516 | xml.Skip();
|
---|
| 517 | break;
|
---|
| 518 | }
|
---|
| 519 | }
|
---|
| 520 |
|
---|
| 521 | xml.ReadEndElement();
|
---|
| 522 | }
|
---|
| 523 |
|
---|
| 524 | return anim;
|
---|
| 525 | }
|
---|
| 526 | }
|
---|
| 527 | }
|
---|