1 | using System.Collections.Generic;
|
---|
2 | using System.Globalization;
|
---|
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 | using Xml;
|
---|
13 |
|
---|
14 | partial class LevelImporter
|
---|
15 | {
|
---|
16 | private void ReadPhysics(XmlReader xml, string basePath)
|
---|
17 | {
|
---|
18 | if (xml.SkipEmpty())
|
---|
19 | return;
|
---|
20 |
|
---|
21 | xml.ReadStartElement("Physics");
|
---|
22 |
|
---|
23 | while (xml.IsStartElement())
|
---|
24 | ReadObjectSetup(xml, basePath);
|
---|
25 |
|
---|
26 | xml.ReadEndElement();
|
---|
27 | }
|
---|
28 |
|
---|
29 | private void ReadObjectSetup(XmlReader xml, string basePath)
|
---|
30 | {
|
---|
31 | var scriptId = -1;
|
---|
32 | var name = xml.GetAttribute("Name");
|
---|
33 | var position = Vector3.Zero;
|
---|
34 | var rotation = Quaternion.Identity;
|
---|
35 | var scale = 1.0f;
|
---|
36 | var flags = ObjectSetupFlags.None;
|
---|
37 | var physicsType = ObjectPhysicsType.None;
|
---|
38 | var particles = new List<ObjectParticle>();
|
---|
39 | var nodes = new List<ObjectNode>();
|
---|
40 | string geometryName = null;
|
---|
41 | string animationName = null;
|
---|
42 |
|
---|
43 | xml.ReadStartElement("Object");
|
---|
44 |
|
---|
45 | while (xml.IsStartElement())
|
---|
46 | {
|
---|
47 | switch (xml.LocalName)
|
---|
48 | {
|
---|
49 | case "Name":
|
---|
50 | name = xml.ReadElementContentAsString();
|
---|
51 | break;
|
---|
52 | case "ScriptId":
|
---|
53 | scriptId = xml.ReadElementContentAsInt();
|
---|
54 | break;
|
---|
55 | case "Flags":
|
---|
56 | flags = xml.ReadElementContentAsEnum<ObjectSetupFlags>() & ~ObjectSetupFlags.InUse;
|
---|
57 | break;
|
---|
58 | case "Position":
|
---|
59 | position = xml.ReadElementContentAsVector3();
|
---|
60 | break;
|
---|
61 | case "Rotation":
|
---|
62 | rotation = xml.ReadElementContentAsEulerXYZ();
|
---|
63 | break;
|
---|
64 | case "Scale":
|
---|
65 | scale = xml.ReadElementContentAsFloat();
|
---|
66 | break;
|
---|
67 | case "Physics":
|
---|
68 | physicsType = xml.ReadElementContentAsEnum<ObjectPhysicsType>();
|
---|
69 | break;
|
---|
70 | case "Particles":
|
---|
71 | particles.AddRange(ReadParticles(xml, basePath));
|
---|
72 | break;
|
---|
73 |
|
---|
74 | case "Geometry":
|
---|
75 | geometryName = xml.ReadElementContentAsString();
|
---|
76 | if (nodes.Count > 0)
|
---|
77 | {
|
---|
78 | error.WriteLine("Geometry cannot be used together with Import, ignoring");
|
---|
79 | break;
|
---|
80 | }
|
---|
81 | break;
|
---|
82 |
|
---|
83 | case "Animation":
|
---|
84 | animationName = xml.ReadElementContentAsString();
|
---|
85 | if (nodes.Count > 0)
|
---|
86 | {
|
---|
87 | error.WriteLine("Animation cannot be used together with Import, ignoring");
|
---|
88 | break;
|
---|
89 | }
|
---|
90 | break;
|
---|
91 |
|
---|
92 | case "Import":
|
---|
93 | if (geometryName != null || animationName != null)
|
---|
94 | {
|
---|
95 | error.WriteLine("Import cannot be used together with Geometry and Animation, ignoring");
|
---|
96 | break;
|
---|
97 | }
|
---|
98 | nodes.AddRange(ImportObjectGeometry(xml, basePath));
|
---|
99 | break;
|
---|
100 |
|
---|
101 | default:
|
---|
102 | error.WriteLine("Unknown physics object element {0}", xml.LocalName);
|
---|
103 | xml.Skip();
|
---|
104 | break;
|
---|
105 | }
|
---|
106 | }
|
---|
107 |
|
---|
108 | xml.ReadEndElement();
|
---|
109 |
|
---|
110 | if (geometryName != null)
|
---|
111 | {
|
---|
112 | var m3gm = FindSharedInstance(TemplateTag.M3GM, geometryName, objectLoadContext);
|
---|
113 | var geometry = GeometryDatReader.Read(m3gm);
|
---|
114 | var animation = new ObjectAnimation[0];
|
---|
115 |
|
---|
116 | if (animationName != null)
|
---|
117 | {
|
---|
118 | var oban = FindSharedInstance(TemplateTag.OBAN, animationName, objectLoadContext);
|
---|
119 | animation = new[] { ObjectDatReader.ReadAnimation(oban) };
|
---|
120 | }
|
---|
121 |
|
---|
122 | nodes.Add(new ObjectNode(new[] { new ObjectGeometry(geometry) }) {
|
---|
123 | FileName = Path.GetFileName(geometryName),
|
---|
124 | Name = m3gm.Name,
|
---|
125 | ScriptId = scriptId,
|
---|
126 | Flags = flags,
|
---|
127 | Animations = animation
|
---|
128 | });
|
---|
129 | }
|
---|
130 |
|
---|
131 | for (int i = 0; i < nodes.Count; i++)
|
---|
132 | {
|
---|
133 | var node = nodes[i];
|
---|
134 |
|
---|
135 | var setup = new ObjectSetup {
|
---|
136 | Name = node.Name,
|
---|
137 | FileName = node.FileName,
|
---|
138 | ScriptId = scriptId++,
|
---|
139 | Flags = flags,
|
---|
140 | PhysicsType = physicsType,
|
---|
141 | };
|
---|
142 |
|
---|
143 | setup.Particles.AddRange(particles);
|
---|
144 |
|
---|
145 | setup.Geometries = node.Geometries
|
---|
146 | .Where(n => (n.Flags & GunkFlags.Invisible) == 0)
|
---|
147 | .Select(n => n.Geometry.Name).ToArray();
|
---|
148 |
|
---|
149 | foreach (var nodeGeometry in node.Geometries.Where(g => (g.Flags & GunkFlags.Invisible) == 0))
|
---|
150 | {
|
---|
151 | var writer = new DatWriter();
|
---|
152 | GeometryDatWriter.Write(nodeGeometry.Geometry, writer.ImporterFile);
|
---|
153 | writer.Write(outputDirPath);
|
---|
154 | }
|
---|
155 |
|
---|
156 | setup.Position = position;
|
---|
157 | setup.Orientation = rotation;
|
---|
158 | setup.Scale = scale;
|
---|
159 | setup.Origin = Matrix.CreateFromQuaternion(setup.Orientation)
|
---|
160 | * Matrix.CreateScale(setup.Scale)
|
---|
161 | * Matrix.CreateTranslation(setup.Position);
|
---|
162 |
|
---|
163 | foreach (var animation in node.Animations)
|
---|
164 | {
|
---|
165 | if (nodes.Count > 1)
|
---|
166 | animation.Name += i.ToString("d2", CultureInfo.InvariantCulture);
|
---|
167 |
|
---|
168 | if ((animation.Flags & ObjectAnimationFlags.Local) != 0)
|
---|
169 | {
|
---|
170 | //animation.Scale = Matrix.CreateScale(setup.Scale);
|
---|
171 |
|
---|
172 | foreach (var key in animation.Keys)
|
---|
173 | {
|
---|
174 | key.Rotation = setup.Orientation * key.Rotation;
|
---|
175 | key.Translation += setup.Position;
|
---|
176 | }
|
---|
177 | }
|
---|
178 |
|
---|
179 | if ((animation.Flags & ObjectAnimationFlags.AutoStart) != 0)
|
---|
180 | {
|
---|
181 | setup.Animation = animation;
|
---|
182 | setup.PhysicsType = ObjectPhysicsType.Animated;
|
---|
183 | }
|
---|
184 |
|
---|
185 | var writer = new DatWriter();
|
---|
186 | ObjectDatWriter.WriteAnimation(animation, writer);
|
---|
187 | writer.Write(outputDirPath);
|
---|
188 | }
|
---|
189 |
|
---|
190 | if (setup.Animation == null && node.Animations.Length > 0)
|
---|
191 | {
|
---|
192 | setup.Animation = node.Animations[0];
|
---|
193 | }
|
---|
194 |
|
---|
195 | if (setup.Animation != null)
|
---|
196 | {
|
---|
197 | var frame0 = setup.Animation.Keys[0];
|
---|
198 |
|
---|
199 | setup.Scale = frame0.Scale.X;
|
---|
200 | setup.Orientation = frame0.Rotation;
|
---|
201 | setup.Position = frame0.Translation;
|
---|
202 | }
|
---|
203 |
|
---|
204 | level.physics.Add(setup);
|
---|
205 | }
|
---|
206 | }
|
---|
207 |
|
---|
208 | private IEnumerable<ObjectNode> ImportObjectGeometry(XmlReader xml, string basePath)
|
---|
209 | {
|
---|
210 | var filePath = xml.GetAttribute("Path");
|
---|
211 |
|
---|
212 | if (filePath == null)
|
---|
213 | filePath = xml.GetAttribute("Url");
|
---|
214 |
|
---|
215 | var scene = LoadScene(Path.Combine(basePath, filePath));
|
---|
216 | var animClips = new List<ObjectAnimationClip>();
|
---|
217 |
|
---|
218 | if (!xml.SkipEmpty())
|
---|
219 | {
|
---|
220 | xml.ReadStartElement();
|
---|
221 |
|
---|
222 | while (xml.IsStartElement())
|
---|
223 | {
|
---|
224 | switch (xml.LocalName)
|
---|
225 | {
|
---|
226 | case "Animation":
|
---|
227 | animClips.Add(ReadAnimationClip(xml));
|
---|
228 | break;
|
---|
229 |
|
---|
230 | default:
|
---|
231 | error.WriteLine("Unknown element {0}", xml.LocalName);
|
---|
232 | xml.Skip();
|
---|
233 | break;
|
---|
234 | }
|
---|
235 | }
|
---|
236 |
|
---|
237 | xml.ReadEndElement();
|
---|
238 | }
|
---|
239 |
|
---|
240 | var importer = new ObjectDaeImporter(textureImporter, null);
|
---|
241 | importer.Import(scene);
|
---|
242 | return importer.Nodes;
|
---|
243 | }
|
---|
244 | }
|
---|
245 | }
|
---|