source: OniSplit/Xml/GenericXmlWriter.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: 7.3 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Globalization;
4using System.Xml;
5using Oni.Imaging;
6using Oni.Metadata;
7
8namespace Oni.Xml
9{
10 internal class GenericXmlWriter : IMetaTypeVisitor
11 {
12 private readonly Action<InstanceDescriptor> exportChild;
13 private readonly XmlWriter xml;
14 private readonly Stack<int> startOffsetStack;
15 private InstanceFile instanceFile;
16 private BinaryReader reader;
17
18 public static void Write(XmlWriter xml, Action<InstanceDescriptor> exportChild, InstanceDescriptor descriptor)
19 {
20 var writer = new GenericXmlWriter(xml, exportChild);
21 writer.WriteInstance(descriptor);
22 }
23
24 private GenericXmlWriter(XmlWriter xml, Action<InstanceDescriptor> exportChild)
25 {
26 this.exportChild = exportChild;
27 this.xml = xml;
28 this.startOffsetStack = new Stack<int>();
29 }
30
31 private void WriteInstance(InstanceDescriptor descriptor)
32 {
33 using (reader = descriptor.OpenRead())
34 {
35 BeginXmlInstance(descriptor);
36 descriptor.Template.Type.Accept(this);
37 EndXmlInstance();
38 }
39 }
40
41 private void BeginXmlInstance(InstanceDescriptor descriptor)
42 {
43 instanceFile = descriptor.File;
44 startOffsetStack.Push(reader.Position - 8);
45
46 string tag = descriptor.Template.Tag.ToString();
47
48 xml.WriteStartElement(tag);
49 xml.WriteAttributeString("id", XmlConvert.ToString(descriptor.Index));
50 }
51
52 private void EndXmlInstance()
53 {
54 startOffsetStack.Pop();
55 xml.WriteEndElement();
56 }
57
58 #region IMetaTypeVisitor Members
59
60 void IMetaTypeVisitor.VisitEnum(MetaEnum type)
61 {
62 type.BinaryToXml(reader, xml);
63 }
64
65 void IMetaTypeVisitor.VisitByte(MetaByte type)
66 {
67 xml.WriteValue(reader.ReadByte());
68 }
69
70 void IMetaTypeVisitor.VisitInt16(MetaInt16 type)
71 {
72 xml.WriteValue(reader.ReadInt16());
73 }
74
75 void IMetaTypeVisitor.VisitUInt16(MetaUInt16 type)
76 {
77 xml.WriteValue(reader.ReadUInt16());
78 }
79
80 void IMetaTypeVisitor.VisitInt32(MetaInt32 type)
81 {
82 xml.WriteValue(reader.ReadInt32());
83 }
84
85 void IMetaTypeVisitor.VisitUInt32(MetaUInt32 type)
86 {
87 xml.WriteValue(reader.ReadUInt32());
88 }
89
90 void IMetaTypeVisitor.VisitInt64(MetaInt64 type)
91 {
92 xml.WriteValue(reader.ReadInt64());
93 }
94
95 void IMetaTypeVisitor.VisitUInt64(MetaUInt64 type)
96 {
97 xml.WriteValue(XmlConvert.ToString(reader.ReadUInt64()));
98 }
99
100 void IMetaTypeVisitor.VisitFloat(MetaFloat type)
101 {
102 xml.WriteValue(reader.ReadSingle());
103 }
104
105 void IMetaTypeVisitor.VisitVector2(MetaVector2 type)
106 {
107 xml.WriteFloatArray(reader.ReadSingleArray(2));
108 }
109
110 void IMetaTypeVisitor.VisitVector3(MetaVector3 type)
111 {
112 xml.WriteFloatArray(reader.ReadSingleArray(3));
113 }
114
115 void IMetaTypeVisitor.VisitMatrix4x3(MetaMatrix4x3 type)
116 {
117 xml.WriteFloatArray(reader.ReadSingleArray(12));
118 }
119
120 void IMetaTypeVisitor.VisitPlane(MetaPlane type)
121 {
122 xml.WriteFloatArray(reader.ReadSingleArray(4));
123 }
124
125 void IMetaTypeVisitor.VisitQuaternion(MetaQuaternion type)
126 {
127 xml.WriteFloatArray(reader.ReadSingleArray(4));
128 }
129
130 void IMetaTypeVisitor.VisitBoundingSphere(MetaBoundingSphere type)
131 {
132 WriteFields(type.Fields);
133 }
134
135 void IMetaTypeVisitor.VisitBoundingBox(MetaBoundingBox type)
136 {
137 WriteFields(type.Fields);
138 }
139
140 void IMetaTypeVisitor.VisitColor(MetaColor type)
141 {
142 Color color = reader.ReadColor();
143
144 if (color.A == 255)
145 xml.WriteValue(string.Format(CultureInfo.InvariantCulture, "{0} {1} {2}", color.R, color.G, color.B));
146 else
147 xml.WriteValue(string.Format(CultureInfo.InvariantCulture, "{0} {1} {2} {3}", color.R, color.G, color.B, color.A));
148 }
149
150 void IMetaTypeVisitor.VisitRawOffset(MetaRawOffset type)
151 {
152 xml.WriteValue(reader.ReadInt32());
153 }
154
155 void IMetaTypeVisitor.VisitSepOffset(MetaSepOffset type)
156 {
157 xml.WriteValue(reader.ReadInt32());
158 }
159
160 void IMetaTypeVisitor.VisitPointer(MetaPointer type)
161 {
162 int id = reader.ReadInt32();
163
164 if (id == 0)
165 {
166 xml.WriteString(string.Empty);
167 return;
168 }
169
170 exportChild(instanceFile.GetDescriptor(id));
171 }
172
173 void IMetaTypeVisitor.VisitString(MetaString type)
174 {
175 xml.WriteValue(reader.ReadString(type.Count));
176 }
177
178 void IMetaTypeVisitor.VisitPadding(MetaPadding type)
179 {
180 reader.Skip(type.Count);
181 }
182
183 void IMetaTypeVisitor.VisitStruct(MetaStruct type)
184 {
185 WriteFields(type.Fields);
186 }
187
188 void IMetaTypeVisitor.VisitArray(MetaArray type)
189 {
190 WriteArray(type.ElementType, type.Count);
191 }
192
193 void IMetaTypeVisitor.VisitVarArray(MetaVarArray type)
194 {
195 int count;
196
197 if (type.CountField.Type == MetaType.Int16)
198 count = reader.ReadInt16();
199 else
200 count = reader.ReadInt32();
201
202 WriteArray(type.ElementType, count);
203 }
204
205 #endregion
206
207 private void WriteFields(IEnumerable<Field> fields)
208 {
209 foreach (var field in fields)
210 {
211 if (field.Type is MetaPadding)
212 {
213 field.Type.Accept(this);
214 continue;
215 }
216
217 string name = field.Name;
218
219 if (string.IsNullOrEmpty(name))
220 {
221 int fieldOffset = reader.Position - startOffsetStack.Peek();
222 name = string.Format(CultureInfo.InvariantCulture, "Offset_{0:X4}", fieldOffset);
223 }
224
225 xml.WriteStartElement(name);
226 field.Type.Accept(this);
227 xml.WriteEndElement();
228 }
229 }
230
231 private void WriteArray(MetaType elementType, int count)
232 {
233 bool simpleArray = elementType.IsBlittable;
234 simpleArray = false;
235
236 for (int i = 0; i < count; i++)
237 {
238 startOffsetStack.Push(reader.Position);
239
240 if (!simpleArray)
241 xml.WriteStartElement(elementType.Name);
242
243 elementType.Accept(this);
244
245 if (!simpleArray)
246 xml.WriteEndElement();
247 else if (i != count - 1)
248 xml.WriteWhitespace(" \n");
249
250 startOffsetStack.Pop();
251 }
252 }
253 }
254}
Note: See TracBrowser for help on using the repository browser.