source: OniSplit/Level/FilmImporter.cs@ 1194

Last change on this file since 1194 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: 9.1 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.IO;
4using System.Xml;
5
6namespace 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}
Note: See TracBrowser for help on using the repository browser.