| 1 | using System; | 
|---|
| 2 | using System.Collections.Generic; | 
|---|
| 3 | using System.IO; | 
|---|
| 4 | using System.Xml; | 
|---|
| 5 |  | 
|---|
| 6 | namespace Oni.Level | 
|---|
| 7 | { | 
|---|
| 8 | using Metadata; | 
|---|
| 9 | using Xml; | 
|---|
| 10 |  | 
|---|
| 11 | partial class LevelImporter | 
|---|
| 12 | { | 
|---|
| 13 | private class Film | 
|---|
| 14 | { | 
|---|
| 15 | public string Name; | 
|---|
| 16 | public Vector3 Position; | 
|---|
| 17 | public float Facing; | 
|---|
| 18 | public float DesiredFacing; | 
|---|
| 19 | public float HeadFacing; | 
|---|
| 20 | public float HeadPitch; | 
|---|
| 21 | public readonly string[] Animations = new string[2]; | 
|---|
| 22 | public int Length; | 
|---|
| 23 | public readonly List<FilmFrame> Frames = new List<FilmFrame>(); | 
|---|
| 24 | } | 
|---|
| 25 |  | 
|---|
| 26 | private class FilmFrame | 
|---|
| 27 | { | 
|---|
| 28 | public Vector2 MouseDelta; | 
|---|
| 29 | public InstanceMetadata.FILMKeys Keys; | 
|---|
| 30 | public uint Time; | 
|---|
| 31 | } | 
|---|
| 32 |  | 
|---|
| 33 | private void ReadFilms(XmlReader xml, string basePath) | 
|---|
| 34 | { | 
|---|
| 35 | if (!xml.IsStartElement("Films") || xml.SkipEmpty()) | 
|---|
| 36 | return; | 
|---|
| 37 |  | 
|---|
| 38 | xml.ReadStartElement("Films"); | 
|---|
| 39 |  | 
|---|
| 40 | while (xml.IsStartElement()) | 
|---|
| 41 | { | 
|---|
| 42 | xml.ReadStartElement("Import"); | 
|---|
| 43 | string filePath = Path.Combine(basePath, xml.ReadElementContentAsString()); | 
|---|
| 44 | xml.ReadEndElement(); | 
|---|
| 45 |  | 
|---|
| 46 | if (!File.Exists(filePath)) | 
|---|
| 47 | { | 
|---|
| 48 | error.WriteLine("Could not find file '{0}'", filePath); | 
|---|
| 49 | continue; | 
|---|
| 50 | } | 
|---|
| 51 |  | 
|---|
| 52 | string extension = Path.GetExtension(filePath); | 
|---|
| 53 | string name = Path.GetFileNameWithoutExtension(filePath); | 
|---|
| 54 |  | 
|---|
| 55 | if (string.Equals(extension, ".oni", StringComparison.OrdinalIgnoreCase)) | 
|---|
| 56 | { | 
|---|
| 57 | var outputFilePath = Path.Combine(outputDirPath, name + ".oni"); | 
|---|
| 58 |  | 
|---|
| 59 | File.Copy(filePath, outputFilePath, true); | 
|---|
| 60 | } | 
|---|
| 61 | else if (string.Equals(extension, ".dat", StringComparison.OrdinalIgnoreCase)) | 
|---|
| 62 | { | 
|---|
| 63 | var film = ReadBinFilm(filePath); | 
|---|
| 64 |  | 
|---|
| 65 | var datWriter = new DatWriter(); | 
|---|
| 66 | WriteDatFilm(datWriter, film); | 
|---|
| 67 | datWriter.Write(outputDirPath); | 
|---|
| 68 | } | 
|---|
| 69 | else if (string.Equals(extension, ".xml", StringComparison.OrdinalIgnoreCase)) | 
|---|
| 70 | { | 
|---|
| 71 | var film = ReadXmlFilm(filePath); | 
|---|
| 72 |  | 
|---|
| 73 | var datWriter = new DatWriter(); | 
|---|
| 74 | WriteDatFilm(datWriter, film); | 
|---|
| 75 | datWriter.Write(outputDirPath); | 
|---|
| 76 | } | 
|---|
| 77 | else | 
|---|
| 78 | { | 
|---|
| 79 | error.WriteLine("Unsupported film file type {0}", extension); | 
|---|
| 80 | } | 
|---|
| 81 | } | 
|---|
| 82 |  | 
|---|
| 83 | xml.ReadEndElement(); | 
|---|
| 84 | } | 
|---|
| 85 |  | 
|---|
| 86 | private static Film ReadBinFilm(string filePath) | 
|---|
| 87 | { | 
|---|
| 88 | string name = Path.GetFileNameWithoutExtension(filePath); | 
|---|
| 89 |  | 
|---|
| 90 | if (name.StartsWith("FILM", StringComparison.Ordinal)) | 
|---|
| 91 | name = name.Substring(4); | 
|---|
| 92 |  | 
|---|
| 93 | var film = new Film(); | 
|---|
| 94 | film.Name = name; | 
|---|
| 95 |  | 
|---|
| 96 | using (var reader = new BinaryReader(filePath, true)) | 
|---|
| 97 | { | 
|---|
| 98 | film.Animations[0] = reader.ReadString(128); | 
|---|
| 99 | film.Animations[1] = reader.ReadString(128); | 
|---|
| 100 | film.Position = reader.ReadVector3(); | 
|---|
| 101 | film.Facing = reader.ReadSingle(); | 
|---|
| 102 | film.DesiredFacing = reader.ReadSingle(); | 
|---|
| 103 | film.HeadFacing = reader.ReadSingle(); | 
|---|
| 104 | film.HeadPitch = reader.ReadSingle(); | 
|---|
| 105 | film.Length = reader.ReadInt32(); | 
|---|
| 106 | reader.Skip(28); | 
|---|
| 107 | int numFrames = reader.ReadInt32(); | 
|---|
| 108 | film.Frames.Capacity = numFrames; | 
|---|
| 109 |  | 
|---|
| 110 | for (int i = 0; i < numFrames; i++) | 
|---|
| 111 | { | 
|---|
| 112 | var frame = new FilmFrame(); | 
|---|
| 113 | frame.MouseDelta = reader.ReadVector2(); | 
|---|
| 114 | frame.Keys = (InstanceMetadata.FILMKeys)reader.ReadUInt64(); | 
|---|
| 115 | frame.Time = reader.ReadUInt32(); | 
|---|
| 116 | reader.Skip(4); | 
|---|
| 117 | film.Frames.Add(frame); | 
|---|
| 118 | } | 
|---|
| 119 | } | 
|---|
| 120 |  | 
|---|
| 121 | return film; | 
|---|
| 122 | } | 
|---|
| 123 |  | 
|---|
| 124 | private static Film ReadXmlFilm(string filePath) | 
|---|
| 125 | { | 
|---|
| 126 | string name = Path.GetFileNameWithoutExtension(filePath); | 
|---|
| 127 |  | 
|---|
| 128 | if (name.StartsWith("FILM", StringComparison.Ordinal)) | 
|---|
| 129 | name = name.Substring(4); | 
|---|
| 130 |  | 
|---|
| 131 | var film = new Film(); | 
|---|
| 132 | film.Name = name; | 
|---|
| 133 |  | 
|---|
| 134 | var settings = new XmlReaderSettings { | 
|---|
| 135 | IgnoreWhitespace = true, | 
|---|
| 136 | IgnoreProcessingInstructions = true, | 
|---|
| 137 | IgnoreComments = true | 
|---|
| 138 | }; | 
|---|
| 139 |  | 
|---|
| 140 | using (var xml = XmlReader.Create(filePath, settings)) | 
|---|
| 141 | { | 
|---|
| 142 | xml.ReadStartElement("Oni"); | 
|---|
| 143 |  | 
|---|
| 144 | name = xml.GetAttribute("Name"); | 
|---|
| 145 |  | 
|---|
| 146 | if (!string.IsNullOrEmpty(name)) | 
|---|
| 147 | film.Name = name; | 
|---|
| 148 |  | 
|---|
| 149 | xml.ReadStartElement("FILM"); | 
|---|
| 150 |  | 
|---|
| 151 | film.Position = xml.ReadElementContentAsVector3("Position"); | 
|---|
| 152 | film.Facing = xml.ReadElementContentAsFloat("Facing", ""); | 
|---|
| 153 | film.DesiredFacing = xml.ReadElementContentAsFloat("DesiredFacing", ""); | 
|---|
| 154 | film.HeadFacing = xml.ReadElementContentAsFloat("HeadFacing", ""); | 
|---|
| 155 | film.HeadPitch = xml.ReadElementContentAsFloat("HeadPitch", ""); | 
|---|
| 156 | film.Length = xml.ReadElementContentAsInt("FrameCount", ""); | 
|---|
| 157 | xml.ReadStartElement("Animations"); | 
|---|
| 158 | film.Animations[0] = xml.ReadElementContentAsString("Link", ""); | 
|---|
| 159 | film.Animations[1] = xml.ReadElementContentAsString("Link", ""); | 
|---|
| 160 | xml.ReadEndElement(); | 
|---|
| 161 | xml.ReadStartElement("Frames"); | 
|---|
| 162 |  | 
|---|
| 163 | while (xml.IsStartElement()) | 
|---|
| 164 | { | 
|---|
| 165 | var frame = new FilmFrame(); | 
|---|
| 166 |  | 
|---|
| 167 | switch (xml.LocalName) | 
|---|
| 168 | { | 
|---|
| 169 | case "FILMFrame": | 
|---|
| 170 | xml.ReadStartElement(); | 
|---|
| 171 | frame.MouseDelta.X = xml.ReadElementContentAsFloat("MouseDeltaX", ""); | 
|---|
| 172 | frame.MouseDelta.Y = xml.ReadElementContentAsFloat("MouseDeltaY", ""); | 
|---|
| 173 | frame.Keys = xml.ReadElementContentAsEnum<InstanceMetadata.FILMKeys>("Keys"); | 
|---|
| 174 | frame.Time = (uint)xml.ReadElementContentAsInt("Frame", ""); | 
|---|
| 175 | xml.ReadEndElement(); | 
|---|
| 176 | break; | 
|---|
| 177 |  | 
|---|
| 178 | case "Frame": | 
|---|
| 179 | xml.ReadStartElement(); | 
|---|
| 180 | while (xml.IsStartElement()) | 
|---|
| 181 | { | 
|---|
| 182 | switch (xml.LocalName) | 
|---|
| 183 | { | 
|---|
| 184 | case "Time": | 
|---|
| 185 | frame.Time = (uint)xml.ReadElementContentAsInt(); | 
|---|
| 186 | break; | 
|---|
| 187 | case "MouseDelta": | 
|---|
| 188 | frame.MouseDelta = xml.ReadElementContentAsVector2(); | 
|---|
| 189 | break; | 
|---|
| 190 | case "Keys": | 
|---|
| 191 | frame.Keys = xml.ReadElementContentAsEnum<InstanceMetadata.FILMKeys>(); | 
|---|
| 192 | break; | 
|---|
| 193 | } | 
|---|
| 194 | } | 
|---|
| 195 | xml.ReadEndElement(); | 
|---|
| 196 | break; | 
|---|
| 197 | default: | 
|---|
| 198 | xml.Skip(); | 
|---|
| 199 | continue; | 
|---|
| 200 | } | 
|---|
| 201 |  | 
|---|
| 202 | film.Frames.Add(frame); | 
|---|
| 203 |  | 
|---|
| 204 | } | 
|---|
| 205 |  | 
|---|
| 206 | xml.ReadEndElement(); | 
|---|
| 207 | xml.ReadEndElement(); | 
|---|
| 208 | } | 
|---|
| 209 |  | 
|---|
| 210 | return film; | 
|---|
| 211 | } | 
|---|
| 212 |  | 
|---|
| 213 | private static void WriteDatFilm(DatWriter filmWriter, Film film) | 
|---|
| 214 | { | 
|---|
| 215 | var descriptor = filmWriter.CreateInstance(TemplateTag.FILM, film.Name); | 
|---|
| 216 |  | 
|---|
| 217 | var animations = new ImporterDescriptor[2]; | 
|---|
| 218 |  | 
|---|
| 219 | for (int i = 0; i < animations.Length; i++) | 
|---|
| 220 | { | 
|---|
| 221 | if (!string.IsNullOrEmpty(film.Animations[i])) | 
|---|
| 222 | animations[i] = filmWriter.CreateInstance(TemplateTag.TRAM, film.Animations[i]); | 
|---|
| 223 | } | 
|---|
| 224 |  | 
|---|
| 225 | using (var writer = descriptor.OpenWrite()) | 
|---|
| 226 | { | 
|---|
| 227 | writer.Write(film.Position); | 
|---|
| 228 | writer.Write(film.Facing); | 
|---|
| 229 | writer.Write(film.DesiredFacing); | 
|---|
| 230 | writer.Write(film.HeadFacing); | 
|---|
| 231 | writer.Write(film.HeadPitch); | 
|---|
| 232 | writer.Write(film.Length); | 
|---|
| 233 | writer.Write(animations); | 
|---|
| 234 | writer.Skip(12); | 
|---|
| 235 | writer.Write(film.Frames.Count); | 
|---|
| 236 |  | 
|---|
| 237 | foreach (var frame in film.Frames) | 
|---|
| 238 | { | 
|---|
| 239 | writer.Write(frame.MouseDelta); | 
|---|
| 240 | writer.Write((ulong)frame.Keys); | 
|---|
| 241 | writer.Write(frame.Time); | 
|---|
| 242 | writer.Skip(4); | 
|---|
| 243 | } | 
|---|
| 244 | } | 
|---|
| 245 | } | 
|---|
| 246 | } | 
|---|
| 247 | } | 
|---|