OSDN Git Service

58ef4b3f8abb91820962f5633b4fc662c32b59b1
[tdcgexplorer/tso2mqo.git] / MqoFile.cs
1 using System;
2 using System.Collections.Generic;
3 using System.IO;
4 using System.Text;
5 using System.Text.RegularExpressions;
6
7 namespace Tso2MqoGui
8 {
9     public class MqoFile
10     {
11         private delegate bool SectionHandler(string[] tokens);
12
13         public static char[] delimiters = new char[] { ' ', '\t' };
14         public static char[] delimiters2 = new char[] { ' ', '\t', '(', ')' };
15
16         private string file;
17         private StreamReader sr;
18         private MqoScene scene;
19         private List<MqoMaterial> materials;
20         private List<MqoObject> objects = new List<MqoObject>();
21         private MqoObject current;
22
23         public MqoScene Scene { get { return scene; } }
24         public List<MqoMaterial> Materials { get { return materials; } }
25         public List<MqoObject> Objects { get { return objects; } }
26
27         public void Load(string file)
28         {
29             using (FileStream fs = File.OpenRead(file))
30             {
31                 this.file = file;
32                 sr = new StreamReader(fs, Encoding.Default);
33                 ReadAll();
34             }
35         }
36
37         public void Dump()
38         {
39             System.Diagnostics.Debug.WriteLine(file);
40             System.Diagnostics.Debug.WriteLine(scene);
41
42             foreach (MqoMaterial i in materials)
43                 System.Diagnostics.Debug.WriteLine(i);
44
45             foreach (MqoObject i in objects)
46                 System.Diagnostics.Debug.WriteLine(i);
47         }
48
49         public void ReadAll()
50         {
51             DoRead(SectionRoot);
52         }
53
54         private static string[] SplitString(string s)
55         {
56             List<string> tokens = new List<string>();
57             StringBuilder sb = new StringBuilder(s.Length);
58             bool str = false;
59             bool escape = false;
60             bool bracket = false;
61             s = s.Trim(' ', '\t', '\r', '\n');
62
63             foreach (char i in s)
64             {
65                 if (escape)
66                 {
67                     sb.Append(i);
68                     escape = false;
69                     continue;
70                 }
71
72
73                 switch (i)
74                 {
75                     case '\\':
76                         if (str) sb.Append(i);
77                         else escape = true;
78                         break;
79                     case ' ':
80                     case '\t':
81                         if (bracket) { sb.Append(i); }
82                         else if (str) { sb.Append(i); }
83                         else if (sb.Length > 0) { tokens.Add(sb.ToString()); sb.Length = 0; }
84                         break;
85                     case '(':
86                         sb.Append(i);
87                         if (!str)
88                             bracket = true;
89                         break;
90                     case ')':
91                         sb.Append(i);
92                         if (!str)
93                             bracket = false;
94                         break;
95                     case '\"':
96                         sb.Append(i);
97                         str = !str;
98                         break;
99                     default:
100                         sb.Append(i);
101                         break;
102                 }
103             }
104
105             if (sb.Length > 0)
106                 tokens.Add(sb.ToString());
107
108             return tokens.ToArray();
109         }
110
111         private void DoRead(SectionHandler h)
112         {
113             for (int no = 1; ; ++no)
114             {
115                 string line = sr.ReadLine();
116
117                 if (line == null)
118                     break;
119
120                 line = line.Trim();
121                 string[] tokens = SplitString(line);
122
123                 try
124                 {
125                     if (tokens.Length == 0)
126                         continue;
127
128                     if (!h(tokens))
129                         break;
130                 }
131                 catch (Exception exception)
132                 {
133                     string msg = string.Format("File format error: {0} \"{1}\"", no, line);
134                     throw new Exception(msg, exception);
135                 }
136             }
137         }
138
139         public void Error(string[] tokens)
140         {
141             throw new Exception("File Format Error: \"" + string.Concat(tokens) + "\"");
142         }
143
144         private bool SectionRoot(string[] tokens)
145         {
146             switch (tokens[0].ToLower())
147             {
148                 case "metasequoia": ParseMetasequoia(tokens); return true;
149                 case "format": ParseFormat(tokens); return true;
150                 case "scene": ParseScene(tokens); return true;
151                 case "material": ParseMaterial(tokens); return true;
152                 case "object": ParseObject(tokens); return true;
153                 case "eof": return false;
154                 //default:            Error(tokens);              return false;
155                 default: return true;
156             }
157         }
158
159         private bool SectionScene(string[] tokens)
160         {
161             scene = new MqoScene();
162
163             switch (tokens[0].ToLower())
164             {
165                 case "pos": scene.pos = Point3.Parse(tokens, 1); return true;
166                 case "lookat": scene.lookat = Point3.Parse(tokens, 1); return true;
167                 case "head": scene.head = float.Parse(tokens[1]); return true;
168                 case "pich": scene.pich = float.Parse(tokens[1]); return true;
169                 case "ortho": scene.ortho = float.Parse(tokens[1]); return true;
170                 case "zoom2": scene.zoom2 = float.Parse(tokens[1]); return true;
171                 case "amb": scene.amb = Color3.Parse(tokens, 1); return true;
172                 case "}": return false;
173                 //default:            Error(tokens);                                  return false;
174                 default: return true;
175             }
176         }
177
178         private static string[] SplitParam(string s)
179         {
180             return s.Split(delimiters2, StringSplitOptions.RemoveEmptyEntries);
181         }
182
183         private bool SectionMaterial(string[] tokens)
184         {
185             if (tokens[0] == "}")
186                 return false;
187
188             StringBuilder sb = new StringBuilder();
189
190             foreach (string i in tokens)
191                 sb.Append(' ').Append(i);
192
193             string line = sb.ToString().Trim();
194             MqoMaterial m = new MqoMaterial(tokens[0].Trim('"'));
195             tokens = SplitString(line);
196             materials.Add(m);
197
198             for (int i = 1; i < tokens.Length; ++i)
199             {
200                 string t = tokens[i];
201                 string t2 = t.ToLower();
202
203                 if (t2.StartsWith("shader(")) m.shader = int.Parse(SplitParam(t)[1]);
204                 else if (t2.StartsWith("col(")) m.col = Color3.Parse(SplitParam(t), 1);
205                 else if (t2.StartsWith("dif(")) m.dif = float.Parse(SplitParam(t)[1]);
206                 else if (t2.StartsWith("amb(")) m.amb = float.Parse(SplitParam(t)[1]);
207                 else if (t2.StartsWith("emi(")) m.emi = float.Parse(SplitParam(t)[1]);
208                 else if (t2.StartsWith("spc(")) m.spc = float.Parse(SplitParam(t)[1]);
209                 else if (t2.StartsWith("power(")) m.power = float.Parse(SplitParam(t)[1]);
210                 else if (t2.StartsWith("tex(")) m.tex = t.Substring(3).Trim('(', ')', '"');
211             }
212
213             return true;
214         }
215
216         private bool SectionObject(string[] tokens)
217         {
218             switch (tokens[0].ToLower())
219             {
220                 case "visible": current.visible = int.Parse(tokens[1]); return true;
221                 case "locking": current.locking = int.Parse(tokens[1]); return true;
222                 case "shading": current.shading = int.Parse(tokens[1]); return true;
223                 case "facet": current.facet = float.Parse(tokens[1]); return true;
224                 case "color": current.color = Color3.Parse(tokens, 1); return true;
225                 case "color_type": current.color_type = int.Parse(tokens[1]); return true;
226                 case "vertex": ParseVertex(tokens); return true;
227                 case "face": ParseFace(tokens); return true;
228                 case "}": return false;
229                 //default:            Error(tokens);                                  return false;
230                 default: return true;
231             }
232         }
233
234         private bool SectionVertex(string[] tokens)
235         {
236             if (tokens[0] == "}")
237                 return false;
238
239             current.vertices.Add(Point3.Parse(tokens, 0));
240
241             return true;
242         }
243
244         private bool SectionFace(string[] tokens)
245         {
246             if (tokens[0] == "}")
247                 return false;
248
249             int nface = int.Parse(tokens[0]);
250             {
251                 StringBuilder sb = new StringBuilder();
252                 foreach (string i in tokens)
253                     sb.Append(' ').Append(i);
254                 string line = sb.ToString().Trim();
255                 tokens = SplitString(line);
256             }
257             switch (nface)
258             {
259                 case 3:
260                     {
261                         MqoFace f = new MqoFace();
262
263                         for (int i = 1; i < tokens.Length; ++i)
264                         {
265                             string t = tokens[i];
266                             string t2 = t.ToLower();
267
268                             if (t2.StartsWith("v("))
269                             {
270                                 string[] t3 = SplitParam(t);
271                                 f.a = ushort.Parse(t3[1]);
272                                 f.b = ushort.Parse(t3[2]);
273                                 f.c = ushort.Parse(t3[3]);
274                             }
275                             else
276                                 if (t2.StartsWith("m("))
277                                 {
278                                     string[] t3 = SplitParam(t);
279                                     f.mtl = ushort.Parse(t3[1]);
280                                 }
281                                 else
282                                     if (t2.StartsWith("uv("))
283                                     {
284                                         string[] t3 = SplitParam(t);
285                                         f.ta = Point2.Parse(t3, 1);
286                                         f.tb = Point2.Parse(t3, 3);
287                                         f.tc = Point2.Parse(t3, 5);
288                                     }
289                         }
290                         current.faces.Add(f);
291                     }
292                     break;
293                 case 4:
294                     {
295                         MqoFace f = new MqoFace();
296                         MqoFace f2 = new MqoFace();
297
298                         for (int i = 1; i < tokens.Length; ++i)
299                         {
300                             string t = tokens[i];
301                             string t2 = t.ToLower();
302
303                             if (t2.StartsWith("v("))
304                             {
305                                 string[] t3 = SplitParam(t);
306                                 f.a = ushort.Parse(t3[1]);
307                                 f.b = ushort.Parse(t3[2]);
308                                 f.c = ushort.Parse(t3[3]);
309                                 f2.a = f.a;
310                                 f2.b = f.c;
311                                 f2.c = ushort.Parse(t3[4]);
312                             }
313                             else
314                                 if (t2.StartsWith("m("))
315                                 {
316                                     string[] t3 = SplitParam(t);
317                                     f.mtl = ushort.Parse(t3[1]);
318                                     f2.mtl = f.mtl;
319                                 }
320                                 else
321                                     if (t2.StartsWith("uv("))
322                                     {
323                                         string[] t3 = SplitParam(t);
324                                         f.ta = Point2.Parse(t3, 1);
325                                         f.tb = Point2.Parse(t3, 3);
326                                         f.tc = Point2.Parse(t3, 5);
327                                         f2.ta = f.ta;
328                                         f2.tb = f.tc;
329                                         f2.tc = Point2.Parse(t3, 7);
330                                     }
331                         }
332                         current.faces.Add(f);
333                         current.faces.Add(f2);
334                     }
335                     break;
336             }
337             return true;
338         }
339
340         //----- Root elements ----------------------------------------------
341         private void ParseMetasequoia(string[] tokens)
342         {
343             if (tokens[1].ToLower() != "document") Error(tokens);
344         }
345
346         private void ParseFormat(string[] tokens)
347         {
348             if (tokens[1].ToLower() != "text") Error(tokens);
349             if (tokens[2].ToLower() != "ver") Error(tokens);
350             if (tokens[3].ToLower() != "1.0") Error(tokens);
351         }
352
353         private void ParseScene(string[] tokens)
354         {
355             if (tokens[1].ToLower() != "{") Error(tokens);
356
357             DoRead(SectionScene);
358         }
359
360         private void ParseMaterial(string[] tokens)
361         {
362             if (tokens[2].ToLower() != "{") Error(tokens);
363
364             materials = new List<MqoMaterial>(int.Parse(tokens[1]));
365             DoRead(SectionMaterial);
366         }
367
368         private void ParseObject(string[] tokens)
369         {
370             if (tokens[2].ToLower() != "{") Error(tokens);
371
372             current = new MqoObject(tokens[1].Trim('"'));
373             objects.Add(current);
374             DoRead(SectionObject);
375         }
376
377         private void ParseVertex(string[] tokens)
378         {
379             if (tokens[2].ToLower() != "{") Error(tokens);
380
381             current.vertices = new List<Point3>(int.Parse(tokens[1]));
382             DoRead(SectionVertex);
383         }
384
385         private void ParseFace(string[] tokens)
386         {
387             if (tokens[2].ToLower() != "{") Error(tokens);
388
389             current.faces = new List<MqoFace>(int.Parse(tokens[1]));
390             DoRead(SectionFace);
391         }
392     }
393
394     public class MqoScene
395     {
396         public Point3 pos;
397         public Point3 lookat;
398         public float head;
399         public float pich;
400         public float ortho;
401         public float zoom2;
402         public Color3 amb;
403
404         public override string ToString()
405         {
406             return (new StringBuilder(256))
407                 .Append(" pos: ").Append(pos)
408                 .Append(" lookat: ").Append(lookat)
409                 .Append(" head: ").Append(head)
410                 .Append(" pich: ").Append(pich)
411                 .Append(" ortho: ").Append(ortho)
412                 .Append(" zoom2: ").Append(zoom2)
413                 .Append(" amb: ").Append(amb)
414                 .ToString();
415         }
416     }
417
418     public class MqoMaterial
419     {
420         public string name;
421         public int shader;
422         public Color3 col;
423         public float dif;
424         public float amb;
425         public float emi;
426         public float spc;
427         public float power;
428         public string tex;
429
430         public MqoMaterial() { }
431         public MqoMaterial(string n) { name = n; }
432
433         public override string ToString()
434         {
435             return (new StringBuilder(256))
436                 .Append(" shader: ").Append(shader)
437                 .Append(" col: ").Append(col)
438                 .Append(" dif: ").Append(dif)
439                 .Append(" amb: ").Append(amb)
440                 .Append(" emi: ").Append(emi)
441                 .Append(" spc: ").Append(spc)
442                 .Append(" power: ").Append(power)
443                 .Append(" tex: ").Append(tex)
444                 .Append(" name: ").Append(name)
445                 .ToString();
446         }
447     }
448
449     public class MqoObject
450     {
451         public string name;
452         public int visible;
453         public int locking;
454         public int shading;
455         public float facet;
456         public Color3 color;
457         public int color_type;
458         public List<Point3> vertices;
459         public List<MqoFace> faces;
460
461         public MqoObject() { }
462         public MqoObject(string n) { name = n; }
463
464         public override string ToString()
465         {
466             return (new StringBuilder(256))
467                 .Append(" visible: ").Append(visible)
468                 .Append(" locking: ").Append(locking)
469                 .Append(" shading: ").Append(shading)
470                 .Append(" facet: ").Append(facet)
471                 .Append(" color: ").Append(color)
472                 .Append(" color_type: ").Append(color_type)
473                 .Append(" vertices: ").Append(vertices.Count)
474                 .Append(" faces: ").Append(faces.Count)
475                 .Append(" name: ").Append(name)
476                 .ToString();
477         }
478     }
479
480     public class MqoFace
481     {
482         public ushort a, b, c, mtl;
483         public Point2 ta, tb, tc;
484
485         public MqoFace()
486         {
487         }
488
489         public MqoFace(ushort a, ushort b, ushort c, ushort mtl, Point2 ta, Point2 tb, Point2 tc)
490         {
491             this.a = a;
492             this.b = b;
493             this.c = c;
494             this.mtl = mtl;
495             this.ta = ta;
496             this.tb = tb;
497             this.tc = tc;
498         }
499
500         public override string ToString()
501         {
502             return (new StringBuilder(256))
503                 .Append("v: ").Append(a).Append(" ").Append(b).Append(" ").Append(c)
504                 .Append(" mtl: ").Append(mtl)
505                 .Append(" uv: ").Append(ta).Append(" ").Append(tb).Append(" ").Append(tc)
506                 .ToString();
507         }
508     }
509 }