2 using System.Collections.Generic;
\r
3 using System.Drawing.Design;
\r
6 using System.Runtime.InteropServices;
\r
7 using System.ComponentModel;
\r
8 using System.Windows.Forms.Design;
\r
10 namespace Tso2MqoGui
\r
12 public abstract class TSOGenerator
\r
15 TSOGeneratorConfig config;
\r
16 protected MqoReader mqo;
\r
17 protected MqxReader mqx;
\r
18 protected TSOFile tsoref;
\r
19 protected List<TSOMesh> meshes;
\r
22 Dictionary<string, MaterialInfo> materials;
\r
23 protected int nummaterials { get { return materials.Count; } }
\r
24 Dictionary<string, TextureInfo> textures;
\r
26 public TSOGenerator(TSOGeneratorConfig config)
\r
28 this.config = config;
\r
31 public TSOFile LoadTSO(string file)
\r
33 TSOFile tso = new TSOFile(file);
\r
38 bool SetCurrentDirectory(string dir)
\r
41 Environment.CurrentDirectory = dir;
\r
45 bool DoLoadMQO(string mqo_file)
\r
48 mqo = new MqoReader();
\r
53 bool DoLoadMqx(string mqo_file)
\r
56 mqx = new MqxReader();
\r
57 if (mqx.Load(mqo_file))
\r
60 mqx.CreateWeitMap();
\r
65 bool DoLoadXml(string importinfo_file)
\r
68 ii = ImportInfo.Load(importinfo_file);
\r
71 materials = new Dictionary<string, MaterialInfo>();
\r
72 bool validmap = true;
\r
74 foreach (MqoMaterial i in mqo.Materials)
\r
76 MaterialInfo mi = new MaterialInfo(dir, i, ii.GetMaterial(i.name));
\r
77 validmap &= mi.Valid;
\r
78 materials.Add(i.name, mi);
\r
81 if (!validmap || config.ShowMaterials)
\r
84 throw new Exception("マテリアルの設定が無効です");
\r
86 FormMaterial dlg = new FormMaterial();
\r
87 dlg.materials = materials;
\r
89 if (dlg.ShowDialog() != System.Windows.Forms.DialogResult.OK)
\r
94 textures = new Dictionary<string, TextureInfo>();
\r
96 foreach (MaterialInfo i in materials.Values)
\r
98 string color_tex_name = Path.GetFileNameWithoutExtension(i.ColorTexture);
\r
100 if (color_tex_name != null && !textures.ContainsKey(color_tex_name))
\r
101 textures.Add(color_tex_name, new TextureInfo(color_tex_name, i.ColorTexture));
\r
103 string shade_tex_name = Path.GetFileNameWithoutExtension(i.ShadeTexture);
\r
105 if (shade_tex_name != null && !textures.ContainsKey(shade_tex_name))
\r
106 textures.Add(shade_tex_name, new TextureInfo(shade_tex_name, i.ShadeTexture));
\r
112 bool DoWriteHeader()
\r
114 bw.Write(0x314F5354);
\r
118 bool DoWriteNodeNames()
\r
120 if (tsoref != null)
\r
122 bw.Write(tsoref.nodes.Length);
\r
124 foreach (TSONode i in tsoref.nodes)
\r
125 WriteString(bw, i.Path);
\r
127 else if (mqx != null)
\r
129 bw.Write(mqx.bones.Length);
\r
131 foreach (MqoBone i in mqx.bones)
\r
132 WriteString(bw, i.path);
\r
140 bool DoWriteNodeMatrices()
\r
142 if (tsoref != null)
\r
144 bw.Write(tsoref.nodes.Length);
\r
146 foreach (TSONode i in tsoref.nodes)
\r
147 WriteMatrix(bw, i.Matrix);
\r
149 else if (mqx != null)
\r
151 bw.Write(mqx.bones.Length);
\r
153 foreach (MqoBone i in mqx.bones)
\r
154 WriteMatrix(bw, i.matrix);
\r
162 bool DoWriteTextures()
\r
164 bw.Write(textures.Count);
\r
166 foreach (TextureInfo tex_info in textures.Values)
\r
168 string file = tex_info.file;
\r
169 string name = tex_info.name;
\r
171 string file_directory_name = Path.GetDirectoryName(file);
\r
172 string file_name = Path.GetFileName(file);
\r
174 WriteString(bw, name);
\r
175 WriteString(bw, "\"" + file_name + "\"");
\r
178 TSOTex tex = LoadTex(file);
\r
180 bw.Write(tex.Width);
\r
181 bw.Write(tex.Height);
\r
182 bw.Write(tex.Depth);
\r
183 bw.Write(tex.data, 0, tex.data.Length);
\r
185 ImportTextureInfo import_tex_info = new ImportTextureInfo(tex);
\r
186 ii.textures.Add(import_tex_info);
\r
188 // テクスチャが同じフォルダにない場合、コピーしておく
\r
189 if (file_directory_name != "" && file_directory_name.ToUpper() != dir.ToUpper())
\r
191 import_tex_info.File = Path.Combine(dir, file_name);
\r
192 File.Copy(file, import_tex_info.File, true);
\r
199 bool DoWriteEffects()
\r
201 bw.Write(ii.effects.Count);
\r
203 foreach (ImportEffectInfo import_effect_info in ii.effects)
\r
205 string file = Path.Combine(dir, import_effect_info.Name);
\r
206 string[] code = File.ReadAllLines(file, Encoding.Default);
\r
208 WriteString(bw, import_effect_info.Name);
\r
209 bw.Write(code.Length);
\r
211 foreach (string line in code)
\r
212 WriteString(bw, line.Trim('\r', '\n'));
\r
218 bool DoWriteMaterials()
\r
220 bw.Write(mqo.Materials.Count);
\r
222 foreach (MqoMaterial mat in mqo.Materials)
\r
224 MaterialInfo mat_info = materials[mat.name];
\r
225 string[] code = mat_info.GetCode();
\r
227 WriteString(bw, mat.name);
\r
228 WriteString(bw, "cgfxShader");
\r
229 bw.Write(code.Length);
\r
231 foreach (string line in code)
\r
232 WriteString(bw, line.Trim('\r', '\n'));
\r
234 ImportMaterialInfo import_mat_info = new ImportMaterialInfo();
\r
235 import_mat_info.Name = mat.name;
\r
236 import_mat_info.File = "cgfxShader";
\r
237 ii.materials.Add(import_mat_info);
\r
240 File.WriteAllLines(Path.Combine(dir, mat.name), code);
\r
246 bool DoWriteMeshes()
\r
248 bw.Write(meshes.Count);
\r
250 foreach (TSOMesh mesh in meshes)
\r
252 WriteString(bw, mesh.Name);
\r
253 WriteMatrix(bw, mesh.Matrix);
\r
255 bw.Write(mesh.numsubs);
\r
257 foreach (TSOSubMesh sub in mesh.sub_meshes)
\r
259 bw.Write(sub.spec);
\r
260 bw.Write(sub.numbones);
\r
262 foreach (int i in sub.bones)
\r
265 bw.Write(sub.numvertices);
\r
267 foreach (Vertex v in sub.vertices)
\r
268 WriteVertex(bw, v);
\r
275 bool DoOutput(string path)
\r
277 //----- 出力処理 -----------------------------------------------
\r
278 ii.materials.Clear();
\r
279 ii.textures.Clear();
\r
281 using (FileStream fs = File.OpenWrite(path))
\r
284 bw = new BinaryWriter(fs);
\r
287 DoWriteNodeNames();
\r
288 DoWriteNodeMatrices();
\r
291 DoWriteMaterials();
\r
292 DoGenerateMeshes();
\r
300 //メッシュリストはthis.meshesに保持する。
\r
301 protected abstract bool DoGenerateMeshes();
\r
303 bool DoSaveXml(string importinfo_file)
\r
306 ImportInfo.Save(importinfo_file, ii);
\r
310 protected virtual bool DoCleanup()
\r
321 System.GC.Collect();
\r
325 public void Generate(string mqo_file, string tsoref_file, string tsoout_file)
\r
327 string dir = Path.GetDirectoryName(mqo_file);
\r
328 string importinfo_file = Path.ChangeExtension(mqo_file, ".xml");
\r
332 if (!SetCurrentDirectory(dir)) return;
\r
333 if (!DoLoadMQO(mqo_file)) return;
\r
334 if (!DoLoadMqx(mqo_file)) return;
\r
335 if (!DoLoadRefTSO(tsoref_file)) return;
\r
336 if (!DoLoadXml(importinfo_file)) return;
\r
337 if (!DoOutput(tsoout_file)) return;
\r
338 if (!DoSaveXml(importinfo_file)) return;
\r
347 // 参照tsoはthis.tsorefに保持する。
\r
348 protected abstract bool DoLoadRefTSO(string path);
\r
351 public void WriteString(BinaryWriter bw, string s)
\r
353 byte[] b = Encoding.Default.GetBytes(s);
\r
358 public void WriteMatrix(BinaryWriter bw, Matrix44 m)
\r
360 bw.Write(m.M11); bw.Write(m.M12); bw.Write(m.M13); bw.Write(m.M14);
\r
361 bw.Write(m.M21); bw.Write(m.M22); bw.Write(m.M23); bw.Write(m.M24);
\r
362 bw.Write(m.M31); bw.Write(m.M32); bw.Write(m.M33); bw.Write(m.M34);
\r
363 bw.Write(m.M41); bw.Write(m.M42); bw.Write(m.M43); bw.Write(m.M44);
\r
366 public unsafe void WriteVertex(BinaryWriter bw, Vertex v)
\r
369 byte* idx = (byte*)(&idx0);
\r
370 List<int> idxs = new List<int>(4);
\r
371 List<float> wgts = new List<float>(4);
\r
373 if (v.Wgt.x > 0) { idxs.Add(idx[0]); wgts.Add(v.Wgt.x); }
\r
374 if (v.Wgt.y > 0) { idxs.Add(idx[1]); wgts.Add(v.Wgt.y); }
\r
375 if (v.Wgt.z > 0) { idxs.Add(idx[2]); wgts.Add(v.Wgt.z); }
\r
376 if (v.Wgt.w > 0) { idxs.Add(idx[3]); wgts.Add(v.Wgt.w); }
\r
378 bw.Write(v.Pos.X); bw.Write(v.Pos.Y); bw.Write(v.Pos.Z);
\r
379 bw.Write(v.Nrm.X); bw.Write(v.Nrm.Y); bw.Write(v.Nrm.Z);
\r
380 bw.Write(v.Tex.X); bw.Write(v.Tex.Y);
\r
382 bw.Write(wgts.Count);
\r
384 for (int i = 0, n = idxs.Count; i < n; ++i)
\r
392 public TSOTex LoadTex(string file)
\r
394 string ext = Path.GetExtension(file).ToUpper();
\r
399 case ".TGA": tex = LoadTarga(file); break;
\r
400 case ".BMP": tex = LoadBitmap(file); break;
\r
401 default: throw new Exception("Unsupported texture file: " + file);
\r
404 for (int i = 0, n = tex.data.Length; i < n; i += tex.Depth)
\r
406 byte b = tex.data[i + 0];
\r
407 tex.data[i + 0] = tex.data[i + 2];
\r
408 tex.data[i + 2] = b;
\r
414 public unsafe TSOTex LoadTarga(string file)
\r
416 using (FileStream fs = File.OpenRead(file))
\r
418 BinaryReader br = new BinaryReader(fs);
\r
419 TARGA_HEADER header;
\r
421 Marshal.Copy(br.ReadBytes(sizeof(TARGA_HEADER)), 0, (IntPtr)(&header), sizeof(TARGA_HEADER));
\r
423 if (header.imagetype != 0x02) throw new Exception("Invalid imagetype: " + file);
\r
424 if (header.depth != 24
\r
425 && header.depth != 32) throw new Exception("Invalid depth: " + file);
\r
427 TSOTex tex = new TSOTex();
\r
428 tex.depth = header.depth / 8;
\r
429 tex.width = header.width;
\r
430 tex.height = header.height;
\r
432 tex.data = br.ReadBytes(tex.width * tex.height * tex.depth);
\r
438 public unsafe TSOTex LoadBitmap(string file)
\r
440 using (FileStream fs = File.OpenRead(file))
\r
442 BinaryReader br = new BinaryReader(fs);
\r
443 BITMAPFILEHEADER bfh;
\r
444 BITMAPINFOHEADER bih;
\r
446 Marshal.Copy(br.ReadBytes(sizeof(BITMAPFILEHEADER)), 0, (IntPtr)(&bfh), sizeof(BITMAPFILEHEADER));
\r
447 Marshal.Copy(br.ReadBytes(sizeof(BITMAPINFOHEADER)), 0, (IntPtr)(&bih), sizeof(BITMAPINFOHEADER));
\r
449 if (bfh.bfType != 0x4D42) throw new Exception("Invalid imagetype: " + file);
\r
450 if (bih.biBitCount != 24
\r
451 && bih.biBitCount != 32) throw new Exception("Invalid depth: " + file);
\r
453 TSOTex tex = new TSOTex();
\r
454 tex.depth = bih.biBitCount / 8;
\r
455 tex.width = bih.biWidth;
\r
456 tex.height = bih.biHeight;
\r
458 tex.data = br.ReadBytes(tex.width * tex.height * tex.depth);
\r
466 public class TextureInfo
\r
468 public string name;
\r
469 public string file;
\r
471 public TextureInfo(string name, string file)
\r
478 public class MaterialInfo
\r
484 //public Dictionary<string, string> parameters;
\r
486 public MaterialInfo(string path, MqoMaterial mat, ImportMaterialInfo import_mat_info)
\r
489 color_tex = mat.tex;
\r
491 if (import_mat_info != null)
\r
493 string file = Path.Combine(path, import_mat_info.Name);
\r
495 if (File.Exists(file))
\r
496 shader = import_mat_info.Name;
\r
498 if (import_mat_info.ShadeTex != null)
\r
500 file = Path.Combine(path, import_mat_info.ShadeTex.File);
\r
502 if (File.Exists(file))
\r
503 shade_tex = import_mat_info.ShadeTex.File;
\r
512 return File.Exists(shader);
\r
516 public string[] GetCode()
\r
518 TSOMaterialCode code = TSOMaterialCode.GenerateFromFile(shader);
\r
519 if (color_tex != null)
\r
520 code.SetValue("ColorTex", Path.GetFileNameWithoutExtension(color_tex));
\r
521 if (shade_tex != null)
\r
522 code.SetValue("ShadeTex", Path.GetFileNameWithoutExtension(shade_tex));
\r
524 List<string> line = new List<string>();
\r
525 foreach (KeyValuePair<string, TSOParameter> i in code)
\r
526 line.Add(i.Value.ToString());
\r
528 return line.ToArray();
\r
531 public string Name { get { return name; } }
\r
533 [Editor(typeof(FileNameEditor), typeof(UITypeEditor))]
\r
534 [DisplayNameAttribute("シェーダー設定ファイル")]
\r
535 public string ShaderFile { get { return shader; } set { shader = value; } }
\r
537 [Editor(typeof(FileNameEditor), typeof(UITypeEditor))]
\r
538 [DisplayNameAttribute("テクスチャ:カラー")]
\r
539 public string ColorTexture { get { return color_tex; } set { color_tex = value; } }
\r
541 [Editor(typeof(FileNameEditor), typeof(UITypeEditor))]
\r
542 [DisplayNameAttribute("テクスチャ:シェーティング")]
\r
543 public string ShadeTexture { get { return shade_tex; } set { shade_tex = value; } }
\r