OSDN Git Service

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