source: OniSplit/Program.cs@ 1116

Last change on this file since 1116 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: 33.8 KB
RevLine 
[1114]1using System;
2using System.Collections.Generic;
3using System.IO;
4using System.Reflection;
5using Oni.Akira;
6using Oni.Collections;
7using Oni.Metadata;
8using Oni.Sound;
9using Oni.Xml;
10
11namespace Oni
12{
13 internal class Program
14 {
15 private static readonly InstanceFileManager fileManager = new InstanceFileManager();
16
17 private static int Main(string[] args)
18 {
19 if (args.Length == 0)
20 {
21 Help(args);
22 Console.WriteLine("Press any key to continue");
23 Console.ReadKey();
24 return 0;
25 }
26
27 if (args[0] == "-cdump")
28 {
29 InstanceMetadata.DumpCStructs(Console.Out);
30 return 0;
31 }
32
33 Dae.IO.DaeReader.CommandLineArgs = args;
34
35 if (args[0] == "-silent")
36 {
37 Console.SetOut(new StreamWriter(Stream.Null));
38 Console.SetError(new StreamWriter(Stream.Null));
39
40 var newArgs = new string[args.Length - 1];
41 Array.Copy(args, 1, newArgs, 0, newArgs.Length);
42 args = newArgs;
43 }
44
45 if (args[0] == "-noexcept")
46 {
47 var newArgs = new string[args.Length - 1];
48 Array.Copy(args, 1, newArgs, 0, newArgs.Length);
49 args = newArgs;
50 return Execute(args);
51 }
52
53 args = AddSearchPaths(args);
54
55 try
56 {
57 return Execute(args);
58 }
59 catch (Exception ex)
60 {
61 Console.Error.WriteLine(ex.ToString());
62 return 1;
63 }
64 }
65
66 private static int Execute(string[] args)
67 {
68 if (args[0].StartsWith("-export:", StringComparison.Ordinal))
69 return Unpack(args);
70
71 switch (args[0])
72 {
73 case "-help":
74 return Help(args);
75
76 case "-version":
77 return PrintVersion();
78
79 case "-export":
80 return Unpack(args);
81
82 case "pack":
83 case "-import":
84 case "-import:nosep":
85 case "-import:sep":
86 case "-import:ppc":
87 case "-import:pc":
88 return Pack(args);
89
90 case "-copy":
91 return Copy(args);
92
93 case "-move":
94 case "-move:overwrite":
95 case "-move:delete":
96 return Move(args);
97
98 case "-list":
99 return List(args);
100
101 case "-deps":
102 return GetDependencies(args);
103
104 case "extract":
105 case "-extract:xml":
106 return ExportXml(args);
107
108 case "-extract:tga":
109 case "-extract:dds":
110 case "-extract:png":
111 case "-extract:jpg":
112 case "-extract:bmp":
113 case "-extract:tif":
114 return ExportTextures(args);
115
116 case "-extract:wav":
117 case "-extract:aif":
118 return ExportSounds(args);
119
120 case "-extract:obj":
121 case "-extract:dae":
122 return ExportGeometry(args);
123
124 case "-extract:txt":
125 return ExportSubtitles(args);
126
127 case "-create:akev":
128 return CreateAkira(args);
129
130 case "-create:tram":
131 case "-create:trbs":
132 case "-create:txmp":
133 case "-create:m3gm":
134 case "-create:subt":
135 case "-create:oban":
136 case "-create":
137 case "create":
138 return CreateGeneric(args);
139
140 case "-grid:create":
141 return CreateGrids(args);
142
143 case "-create:level":
144 return ImportLevel(args);
145
146 case "-room:extract":
147 return ExtractRooms(args);
148
149 case "film2xml":
150 return ConvertFilm2Xml(args);
151
152 default:
153 Console.Error.WriteLine("Unknown command {0}", args[0]);
154 return 1;
155 }
156 }
157
158 private static string[] AddSearchPaths(string[] args)
159 {
160 List<string> newArgs = new List<string>();
161
162 for (int i = 0; i < args.Length; i++)
163 {
164 if (args[i] == "-search")
165 {
166 i++;
167
168 if (i < args.Length)
169 fileManager.AddSearchPath(args[i]);
170 }
171 else
172 {
173 newArgs.Add(args[i]);
174 }
175 }
176
177 return newArgs.ToArray();
178 }
179
180 private static int Help(string[] args)
181 {
182 if (args.Length > 1 && args[1] == "enums")
183 {
184 HelpEnums();
185 return 0;
186 }
187
188 Console.WriteLine("{0} [options] datfile", Environment.GetCommandLineArgs()[0]);
189 Console.WriteLine();
190 Console.WriteLine("Options:");
191 Console.WriteLine("\t-export <directory>\t\tExport a Oni .dat file to directory");
192 Console.WriteLine("\t-import <directory>\t\tImport a Oni .dat file from directory");
193 Console.WriteLine("\t\t\t\t\tTarget file format is determined from source files (when possible)");
194 Console.WriteLine("\t-import:sep <directory>\t\tImport a Oni .dat file from directory");
195 Console.WriteLine("\t\t\t\t\tCreate a .dat file that uses .raw and .sep binary files (Mac and PC Demo)");
196 Console.WriteLine("\t-import:nosep <directory>\tImport a Oni .dat file from directory");
197 Console.WriteLine("\t\t\t\t\tCreate a .dat file that uses only .raw binary file (PC)");
198 Console.WriteLine();
199 Console.WriteLine("\t-extract:dds <directory>\tExtracts all textures (TXMP) from a Oni .dat/.oni file in DDS format");
200 Console.WriteLine("\t-extract:tga <directory>\tExtracts all textures (TXMP) from a Oni .dat/.oni file in TGA format");
201 Console.WriteLine("\t-extract:png <directory>\tExtracts all textures (TXMP) from a Oni .dat/.oni file in PNG format");
202 Console.WriteLine("\t-extract:wav <directory>\tExtracts all sounds (SNDD) from a Oni .dat/.oni file in WAV format");
203 Console.WriteLine("\t-extract:aif <directory>\tExtracts all sounds (SNDD) from a Oni .dat/.oni file in AIF format");
204 Console.WriteLine("\t-extract:txt <directory>\tExtracts all subtitles (SUBT) from a Oni .dat/.oni file in TXT format");
205 Console.WriteLine("\t-extract:obj <directory>\tExtracts all M3GM and ONCC instances to Wavefront OBJ files");
206 Console.WriteLine("\t-extract:dae <directory>\tExtracts all M3GM and ONCC instances to Collada files");
207 Console.WriteLine("\t-extract:xml <directory>\tExtracts all instances to XML files");
208 Console.WriteLine();
209 Console.WriteLine("\t-create:txmp <directory> [-nomipmaps] [-nouwrap] [-novwrap] [-format:bgr|rgba|bgr555|bgra5551|bgra4444|dxt1] [-envmap:texture_name] [-large] image_file");
210 Console.WriteLine("\t-create:m3gm <directory> [-tex:texture_name] obj_file");
211 Console.WriteLine("\t-create:trbs <directory> dae_file");
212 Console.WriteLine("\t-create:subt <directory> txt_file");
213 Console.WriteLine("\t-create <directory> xml_file\tCreates an .oni file from an XML file");
214 Console.WriteLine();
215 Console.WriteLine("\t-grid:create -out:<directory> rooms_src.dae level_geometry1.dae level_geometry2.dae ...\tGenerates pathfinding grids");
216 Console.WriteLine();
217 Console.WriteLine("\t-list\t\t\t\tLists the named instances contained in datfile");
218 Console.WriteLine("\t-copy <directory>\t\tCopy an exported .oni file and its dependencies to directory");
219 Console.WriteLine("\t-move <directory>\t\tMove an exported .oni file and its dependencies to directory");
220 Console.WriteLine("\t-move:overwrite <directory>\tMove an exported .oni file and its dependencies to directory");
221 Console.WriteLine("\t\t\t\t\tOverwrites any existing files");
222 Console.WriteLine("\t-move:delete <directory>\tMove an exported .oni file and its dependencies to directory");
223 Console.WriteLine("\t\t\t\t\tDeletes files at source when they already exist at destination");
224 Console.WriteLine("\t-deps\t\t\t\tGet a list of exported .oni files the specified files depends on");
225 Console.WriteLine("\t-version\t\t\tShow OniSplit versions");
226 Console.WriteLine("\t-help\t\t\t\tShow this help");
227 Console.WriteLine("\t-help enums\t\t\tShow a list of enums and flags used in XML files");
228 Console.WriteLine();
229
230 return 0;
231 }
232
233 private static void HelpEnums()
234 {
235 WriteEnums(typeof(InstanceMetadata));
236 WriteEnums(typeof(ObjectMetadata));
237
238 Console.WriteLine("-----------------------------------------------------");
239 Console.WriteLine("Particles enums");
240 Console.WriteLine("-----------------------------------------------------");
241 Console.WriteLine();
242
243 Utils.WriteEnum(typeof(Particles.ParticleFlags1));
244 Utils.WriteEnum(typeof(Particles.ParticleFlags2));
245 Utils.WriteEnum(typeof(Particles.EmitterFlags));
246 Utils.WriteEnum(typeof(Particles.EmitterOrientation));
247 Utils.WriteEnum(typeof(Particles.EmitterPosition));
248 Utils.WriteEnum(typeof(Particles.EmitterRate));
249 Utils.WriteEnum(typeof(Particles.EmitterSpeed));
250 Utils.WriteEnum(typeof(Particles.EmitterDirection));
251 Utils.WriteEnum(typeof(Particles.DisableDetailLevel));
252 Utils.WriteEnum(typeof(Particles.AttractorSelector));
253 Utils.WriteEnum(typeof(Particles.AttractorTarget));
254 Utils.WriteEnum(typeof(Particles.EventType));
255 Utils.WriteEnum(typeof(Particles.SpriteType));
256 Utils.WriteEnum(typeof(Particles.StorageType));
257 Utils.WriteEnum(typeof(Particles.ValueType));
258
259 Console.WriteLine("-----------------------------------------------------");
260 Console.WriteLine("Object enums");
261 Console.WriteLine("-----------------------------------------------------");
262 Console.WriteLine();
263
264 Utils.WriteEnum(typeof(Physics.ObjectSetupFlags));
265 Utils.WriteEnum(typeof(Physics.ObjectPhysicsType));
266 Utils.WriteEnum(typeof(Physics.ObjectAnimationFlags));
267 }
268
269 private static void WriteEnums(Type type)
270 {
271#if !NETCORE
272 foreach (var enumType in type.GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic))
273 {
274 if (!enumType.IsEnum)
275 continue;
276
277 Utils.WriteEnum(enumType);
278 }
279#endif
280 }
281
282 private static int Unpack(string[] args)
283 {
284 if (args.Length < 3)
285 {
286 Console.Error.WriteLine("Invalid command line.");
287 return 1;
288 }
289
290 var prefixes = new List<string>();
291 string outputDirPath = null;
292 string sourceFilePath = null;
293
294 foreach (string arg in args)
295 {
296 if (arg.StartsWith("-export", StringComparison.Ordinal))
297 {
298 string prefix = null;
299 int i = arg.IndexOf(':');
300
301 if (i != -1)
302 prefix = arg.Substring(i + 1);
303
304 if (!string.IsNullOrEmpty(prefix))
305 prefixes.Add(prefix);
306 }
307 else if (outputDirPath == null)
308 {
309 outputDirPath = Path.GetFullPath(arg);
310 }
311 else if (sourceFilePath == null)
312 {
313 sourceFilePath = Path.GetFullPath(arg);
314 }
315 }
316
317 var unpacker = new DatUnpacker(fileManager, outputDirPath);
318
319 if (prefixes.Count > 0)
320 unpacker.NameFilter = Utils.WildcardToRegex(prefixes);
321
322 unpacker.ExportFiles(new[] { sourceFilePath });
323
324 return 0;
325 }
326
327 private static int ExportTextures(string[] args)
328 {
329 if (args.Length < 3)
330 {
331 Console.Error.WriteLine("Invalid command line.");
332 return 1;
333 }
334
335 int i = args[0].IndexOf(':');
336 string fileType = null;
337
338 if (i != -1)
339 fileType = args[0].Substring(i + 1);
340
341 var outputDirPath = Path.GetFullPath(args[1]);
342 var sourceFilePaths = GetFileList(args, 2);
343
344 var exporter = new Oni.Motoko.TextureExporter(fileManager, outputDirPath, fileType);
345 exporter.ExportFiles(sourceFilePaths);
346
347 return 0;
348 }
349
350 private static int ExportSounds(string[] args)
351 {
352 if (args.Length < 3)
353 {
354 Console.Error.WriteLine("Invalid command line.");
355 return 1;
356 }
357
358 int i = args[0].IndexOf(':');
359 string fileType = null;
360
361 if (i != -1)
362 fileType = args[0].Substring(i + 1);
363
364 var outputDirPath = Path.GetFullPath(args[1]);
365 var sourceFilePaths = GetFileList(args, 2);
366
367 SoundExporter exporter;
368
369 switch (fileType)
370 {
371 case "aif":
372 exporter = new AifExporter(fileManager, outputDirPath);
373 break;
374 case "wav":
375 exporter = new WavExporter(fileManager, outputDirPath);
376 break;
377 default:
378 throw new NotSupportedException(string.Format("Unsupported file type {0}", fileType));
379 }
380
381 exporter.ExportFiles(sourceFilePaths);
382
383 return 0;
384 }
385
386 private static int ExportGeometry(string[] args)
387 {
388 if (args.Length < 3)
389 {
390 Console.Error.WriteLine("Invalid command line.");
391 return 1;
392 }
393
394 int i = args[0].IndexOf(':');
395 string fileType = null;
396
397 if (i != -1)
398 fileType = args[0].Substring(i + 1);
399
400 var outputDirPath = Path.GetFullPath(args[1]);
401 var sourceFilePaths = GetFileList(args, 2);
402
403 var exporter = new DaeExporter(args, fileManager, outputDirPath, fileType);
404 exporter.ExportFiles(sourceFilePaths);
405
406 return 0;
407 }
408
409 private static int ExportSubtitles(string[] args)
410 {
411 if (args.Length < 3)
412 {
413 Console.Error.WriteLine("Invalid command line.");
414 return 1;
415 }
416
417 var outputDirPath = Path.GetFullPath(args[1]);
418 var sourceFilePaths = GetFileList(args, 2);
419
420 var exporter = new SubtitleExporter(fileManager, outputDirPath);
421 exporter.ExportFiles(sourceFilePaths);
422
423 return 0;
424 }
425
426 private static int ExportXml(string[] args)
427 {
428 if (args.Length < 3)
429 {
430 Console.Error.WriteLine("Invalid command line.");
431 return 1;
432 }
433
434 var outputDirPath = Path.GetFullPath(args[1]);
435 var sourceFilePaths = GetFileList(args, 2);
436
437 var exporter = new XmlExporter(fileManager, outputDirPath)
438 {
439 Recursive = args.Any(a => a == "-recurse"),
440 MergeAnimations = args.Any(a => a == "-anim-merge"),
441 NoAnimation = args.Any(a => a == "-noanim")
442 };
443
444 var animBodyFilePath = args.FirstOrDefault(a => a.StartsWith("-anim-body:", StringComparison.Ordinal));
445
446 if (animBodyFilePath != null)
447 {
448 animBodyFilePath = Path.GetFullPath(animBodyFilePath.Substring("-anim-body:".Length));
449 var file = fileManager.OpenFile(animBodyFilePath);
450 exporter.AnimationBody = Totoro.BodyDatReader.Read(file.Descriptors[0]);
451 }
452
453 exporter.ExportFiles(sourceFilePaths);
454
455 return 0;
456 }
457
458 private static int Pack(string[] args)
459 {
460 if (args.Length < 3)
461 {
462 Console.Error.WriteLine("Invalid command line.");
463 return 1;
464 }
465
466 var packer = new DatPacker();
467 var inputPaths = new List<string>();
468
469 if (args[0] == "pack")
470 {
471 for (int i = 1; i < args.Length; i++)
472 {
473 var arg = args[i];
474
475 if (arg == "-out")
476 {
477 i++;
478 packer.TargetFilePath = Path.GetFullPath(args[i]);
479 continue;
480 }
481
482 if (arg.StartsWith("-type:", StringComparison.Ordinal))
483 {
484 switch (arg.Substring(6))
485 {
486 case "nosep":
487 case "pc":
488 packer.TargetTemplateChecksum = InstanceFileHeader.OniPCTemplateChecksum;
489 break;
490
491 case "sep":
492 case "pcdemo":
493 case "macintel":
494 packer.TargetTemplateChecksum = InstanceFileHeader.OniMacTemplateChecksum;
495 break;
496
497 case "ppc":
498 packer.TargetTemplateChecksum = InstanceFileHeader.OniMacTemplateChecksum;
499 packer.TargetBigEndian = true;
500 break;
501
502 default:
503 throw new ArgumentException(string.Format("Unknown output type {0}", arg.Substring(6)));
504 }
505
506 continue;
507 }
508
509 if (Directory.Exists(arg))
510 {
511 arg = Path.GetFullPath(arg);
512 Console.WriteLine("Reading directory {0}", arg);
513 inputPaths.AddRange(Directory.GetFiles(arg, "*.oni", SearchOption.AllDirectories));
514 }
515 else
516 {
517 var dirPath = Path.GetDirectoryName(arg);
518 var fileSpec = Path.GetFileName(arg);
519
520 if (string.IsNullOrEmpty(dirPath))
521 dirPath = Directory.GetCurrentDirectory();
522 else
523 dirPath = Path.GetFullPath(dirPath);
524
525 if (Directory.Exists(dirPath))
526 {
527 foreach (string filePath in Directory.GetFiles(dirPath, fileSpec))
528 {
529 Console.WriteLine("Reading {0}", filePath);
530 inputPaths.Add(filePath);
531 }
532 }
533 }
534 }
535
536 packer.Pack(fileManager, inputPaths);
537 }
538 else
539 {
540 switch (args[0])
541 {
542 case "-import:nosep":
543 case "-import:pc":
544 packer.TargetTemplateChecksum = InstanceFileHeader.OniPCTemplateChecksum;
545 break;
546
547 case "-import:sep":
548 case "-import:pcdemo":
549 case "-import:macintel":
550 packer.TargetTemplateChecksum = InstanceFileHeader.OniMacTemplateChecksum;
551 break;
552
553 case "-import:ppc":
554 packer.TargetTemplateChecksum = InstanceFileHeader.OniMacTemplateChecksum;
555 packer.TargetBigEndian = true;
556 break;
557 }
558
559 for (int i = 1; i < args.Length - 1; i++)
560 inputPaths.Add(Path.GetFullPath(args[i]));
561
562 packer.TargetFilePath = Path.GetFullPath(args[args.Length - 1]);
563 packer.Import(fileManager, inputPaths.ToArray());
564 }
565
566 return 0;
567 }
568
569 private static int Copy(string[] args)
570 {
571 if (args.Length < 3)
572 {
573 Console.Error.WriteLine("Invalid command line.");
574 return 1;
575 }
576
577 var outputDirPath = Path.GetFullPath(args[1]);
578 var inputFilePaths = GetFileList(args, 2);
579 var copy = new InstanceFileOperations();
580
581 copy.Copy(fileManager, inputFilePaths, outputDirPath);
582
583 return 0;
584 }
585
586 private static int Move(string[] args)
587 {
588 if (args.Length < 3)
589 {
590 Console.Error.WriteLine("Invalid command line.");
591 return 1;
592 }
593
594 var outputDirPath = Path.GetFullPath(args[1]);
595 var inputFilePaths = GetFileList(args, 2);
596 var copy = new InstanceFileOperations();
597
598 if (args[0] == "-move:delete")
599 copy.MoveDelete(fileManager, inputFilePaths, outputDirPath);
600 else if (args[0] == "-move:overwrite")
601 copy.MoveOverwrite(fileManager, inputFilePaths, outputDirPath);
602 else
603 copy.Move(fileManager, inputFilePaths, outputDirPath);
604
605 return 0;
606 }
607
608 private static int List(string[] args)
609 {
610 if (args.Length < 2)
611 {
612 Console.Error.WriteLine("Invalid command line.");
613 return 1;
614 }
615
616 string sourceFilePath = Path.GetFullPath(args[1]);
617
618 var file = fileManager.OpenFile(sourceFilePath);
619
620 foreach (var descriptor in file.GetNamedDescriptors())
621 Console.WriteLine(descriptor.FullName);
622
623 return 0;
624 }
625
626 private static int GetDependencies(string[] args)
627 {
628 if (args.Length < 2)
629 {
630 Console.Error.WriteLine("Invalid command line.");
631 return 1;
632 }
633
634 var inputFilePaths = GetFileList(args, 1);
635
636 InstanceFileOperations copy = new InstanceFileOperations();
637 copy.GetDependencies(fileManager, inputFilePaths);
638
639 return 0;
640 }
641
642 private static int PrintVersion()
643 {
644 Console.WriteLine("OniSplit version {0}", Utils.Version);
645 return 0;
646 }
647
648 private static int CreateGrids(string[] args)
649 {
650 if (args.Length < 2)
651 {
652 Console.Error.WriteLine("Invalid command line.");
653 return 1;
654 }
655
656 var filePaths = GetFileList(args, 1);
657
658 var roomsScene = Dae.Reader.ReadFile(filePaths[0]);
659 var geometryMesh = Akira.AkiraDaeReader.Read(filePaths.Skip(1));
660 var gridBuilder = new Akira.RoomGridBuilder(roomsScene, geometryMesh);
661 string outputDirPath = null;
662
663 foreach (string arg in args)
664 {
665 if (arg.StartsWith("-out:", StringComparison.Ordinal))
666 outputDirPath = Path.GetFullPath(arg.Substring(5));
667 }
668
669 if (string.IsNullOrEmpty(outputDirPath))
670 {
671 Console.Error.WriteLine("Output path must be specified");
672 return 1;
673 }
674
675 gridBuilder.Build();
676 AkiraDaeWriter.WriteRooms(gridBuilder.Mesh, Path.GetFileNameWithoutExtension(filePaths[0]), outputDirPath);
677
678 return 0;
679 }
680
681 private static int ExtractRooms(string[] args)
682 {
683 if (args.Length < 2)
684 {
685 Console.Error.WriteLine("Invalid command line.");
686 return 1;
687 }
688
689 string outputFilePath = null;
690
691 foreach (string arg in args)
692 {
693 if (arg.StartsWith("-out:", StringComparison.Ordinal))
694 outputFilePath = Path.GetFullPath(arg.Substring(5));
695 }
696
697 if (string.IsNullOrEmpty(outputFilePath))
698 {
699 Console.Error.WriteLine("Output file path must be specified");
700 return 1;
701 }
702
703 var extractor = new Akira.RoomExtractor(GetFileList(args, 1), outputFilePath);
704 extractor.Extract();
705 return 0;
706 }
707
708 private static int CreateAkira(string[] args)
709 {
710 if (args.Length < 2)
711 {
712 Console.Error.WriteLine("Invalid command line.");
713 return 1;
714 }
715
716 var outputDirPath = Path.GetFullPath(args[1]);
717 var filePaths = GetFileList(args, 2);
718
719 Directory.CreateDirectory(outputDirPath);
720
721 var importedFiles = new Set<string>(StringComparer.OrdinalIgnoreCase);
722 var taskQueue = new Queue<ImporterTask>();
723
724 foreach (string filePath in filePaths)
725 importedFiles.Add(filePath);
726
727 var importer = new AkiraImporter(args);
728
729 Console.WriteLine("Importing {0}", filePaths[0]);
730
731 importer.Import(filePaths, outputDirPath);
732
733 QueueTasks(importedFiles, taskQueue, importer);
734 ExecuteTasks(args, outputDirPath, importedFiles, taskQueue);
735
736 return 0;
737 }
738
739 private static int CreateGeneric(string[] args)
740 {
741 if (args.Length < 2)
742 {
743 Console.Error.WriteLine("Invalid command line.");
744 return 1;
745 }
746
747 var targetType = TemplateTag.NONE;
748 int colonIndex = args[0].IndexOf(':');
749
750 if (colonIndex != -1)
751 {
752 string tagName = args[0].Substring(colonIndex + 1);
753 targetType = (TemplateTag)Enum.Parse(typeof(TemplateTag), tagName, true);
754 }
755
756 string outputDirPath = Path.GetFullPath(args[1]);
757 var filePaths = GetFileList(args, 2);
758
759 Directory.CreateDirectory(outputDirPath);
760
761 var importedFiles = new Set<string>(StringComparer.OrdinalIgnoreCase);
762 var importQueue = new Queue<ImporterTask>();
763
764 foreach (string filePath in filePaths)
765 {
766 if (importedFiles.Add(filePath))
767 importQueue.Enqueue(new ImporterTask(filePath, targetType));
768 }
769
770 ExecuteTasks(args, outputDirPath, importedFiles, importQueue);
771
772 return 0;
773 }
774
775 private static void ExecuteTasks(string[] args, string outputDirPath, Set<string> importedFiles, Queue<ImporterTask> taskQueue)
776 {
777 while (taskQueue.Count > 0)
778 {
779 var task = taskQueue.Dequeue();
780
781 if (!File.Exists(task.FilePath))
782 {
783 Console.Error.WriteLine("File {0} does not exist", task.FilePath);
784 continue;
785 }
786
787 var importer = CreateImporterFromFileName(args, task);
788
789 if (importer == null)
790 {
791 Console.Error.WriteLine("{0} files cannot be imported as {1}", Path.GetExtension(task.FilePath), task.Type);
792 continue;
793 }
794
795 Console.WriteLine("Importing {0}", task.FilePath);
796
797 importer.Import(task.FilePath, outputDirPath);
798
799 QueueTasks(importedFiles, taskQueue, importer);
800 }
801 }
802
803 private static Importer CreateImporterFromFileName(string[] args, ImporterTask task)
804 {
805 Importer importer = null;
806
807 switch (Path.GetExtension(task.FilePath).ToLowerInvariant())
808 {
809 case ".bin":
810 importer = new BinImporter();
811 break;
812
813 case ".xml":
814 importer = new XmlImporter(args);
815 break;
816
817 case ".tga":
818 case ".dds":
819 case ".png":
820 case ".jpg":
821 case ".bmp":
822 case ".tif":
823 if (task.Type == TemplateTag.NONE || task.Type == TemplateTag.TXMP)
824 importer = new Oni.Motoko.TextureImporter(args);
825 break;
826
827 case ".obj":
828 case ".dae":
829 if (task.Type == TemplateTag.NONE || task.Type == TemplateTag.M3GM)
830 importer = new Motoko.GeometryImporter(args);
831 else if (task.Type == TemplateTag.AKEV)
832 importer = new AkiraImporter(args);
833 else if (task.Type == TemplateTag.TRBS)
834 importer = new Totoro.BodySetImporter(args);
835 else if (task.Type == TemplateTag.OBAN)
836 importer = new Physics.ObjectAnimationImporter(args);
837 break;
838
839 case ".wav":
840 if (task.Type == TemplateTag.NONE || task.Type == TemplateTag.SNDD)
841 importer = new WavImporter();
842 break;
843
844 case ".aif":
845 case ".aifc":
846 case ".afc":
847 if (task.Type == TemplateTag.NONE || task.Type == TemplateTag.SNDD)
848 importer = new AifImporter();
849 break;
850
851 case ".txt":
852 if (task.Type == TemplateTag.NONE || task.Type == TemplateTag.SUBT)
853 importer = new SubtitleImporter();
854 break;
855 }
856
857 return importer;
858 }
859
860 private static void QueueTasks(Set<string> imported, Queue<ImporterTask> importQueue, Importer importer)
861 {
862 foreach (ImporterTask child in importer.Dependencies)
863 {
864 if (!imported.Contains(child.FilePath))
865 {
866 imported.Add(child.FilePath);
867 importQueue.Enqueue(child);
868 }
869 }
870 }
871
872 private static int ConvertFilm2Xml(string[] args)
873 {
874 if (args.Length < 3)
875 {
876 Console.Error.WriteLine("Invalid command line.");
877 return 1;
878 }
879
880 var outputDirPath = Path.GetFullPath(args[1]);
881 var inputFilePaths = GetFileList(args, 2);
882
883 Directory.CreateDirectory(outputDirPath);
884
885 foreach (string filePath in inputFilePaths)
886 FilmToXmlConverter.Convert(filePath, outputDirPath);
887
888 return 0;
889 }
890
891 private static int ImportLevel(string[] args)
892 {
893 if (args.Length < 2)
894 {
895 Console.Error.WriteLine("Invalid command line.");
896 return 1;
897 }
898
899 var levelImporter = new Level.LevelImporter
900 {
901 Debug = args.Any(a => a == "-debug")
902 };
903
904 var outputDirPath = Path.GetFullPath(args[1]);
905
906 if (string.IsNullOrEmpty(outputDirPath))
907 {
908 Console.Error.WriteLine("Output path must be specified");
909 return 1;
910 }
911
912 var inputFiles = GetFileList(args, 2);
913
914 if (inputFiles.Count == 0)
915 {
916 Console.Error.WriteLine("No input files specified");
917 return 1;
918 }
919
920 if (inputFiles.Count > 1)
921 {
922 Console.Error.WriteLine("Too many input files specified, only one level can be created at a time");
923 return 1;
924 }
925
926 levelImporter.Import(inputFiles[0], outputDirPath);
927 return 0;
928 }
929
930 private static List<string> GetFileList(string[] args, int startIndex)
931 {
932 var fileSet = new Set<string>(StringComparer.OrdinalIgnoreCase);
933 var fileList = new List<string>();
934
935 foreach (var arg in args.Skip(startIndex))
936 {
937 if (arg[0] == '-')
938 continue;
939
940 string dirPath = Path.GetDirectoryName(arg);
941 string fileSpec = Path.GetFileName(arg);
942
943 if (string.IsNullOrEmpty(dirPath))
944 dirPath = Directory.GetCurrentDirectory();
945 else
946 dirPath = Path.GetFullPath(dirPath);
947
948 if (Directory.Exists(dirPath))
949 {
950 foreach (string filePath in Directory.GetFiles(dirPath, fileSpec))
951 {
952 if (fileSet.Add(filePath))
953 fileList.Add(filePath);
954 }
955 }
956 }
957
958 if (fileList.Count == 0)
959 throw new ArgumentException("No input files found");
960
961 return fileList;
962 }
963 }
964}
Note: See TracBrowser for help on using the repository browser.