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