OSDN Git Service

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