| 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 | }
|
|---|