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;
\r
9 using System.Windows.Forms.Design;
\r
11 namespace Tso2MqoGui
\r
13 public unsafe class TSOGenerator
\r
16 private TSOGenerateConfig config;
\r
17 private PointCluster pc;
\r
18 private MqoFile mqo;
\r
19 private TSOFile tsor;
\r
20 private List<Vertex> vlst;
\r
21 private Dictionary<string, TSONode> nodes;
\r
22 private List<TSOMesh> meshes;
\r
23 private string mqoin;
\r
24 private string tsoref;
\r
25 private string tsoex;
\r
26 private ImportInfo ii;
\r
27 private BinaryWriter bw;
\r
28 private Dictionary<string, MaterialInfo> materials;
\r
29 private Dictionary<string, TextureInfo> textures;
\r
31 public TSOFile LoadTSO(string file)
\r
33 TSOFile tso = new TSOFile(file);
\r
38 private void CreatePointCluster(TSOFile tso)
\r
40 vlst= new List<Vertex>();
\r
42 foreach(TSOMesh i in tso.meshes)
\r
43 foreach(TSOSubMesh j in i.sub)
\r
44 vlst.AddRange(j.vertices);
\r
46 pc = new PointCluster(vlst.Count);
\r
48 foreach(Vertex i in vlst)
\r
49 pc.Add(i.Pos.x, i.Pos.y, i.Pos.z);
\r
54 private bool Common_DoSetupDir()
\r
56 Environment.CurrentDirectory= dir= Path.GetDirectoryName(mqoin);
\r
60 private bool Common_DoLoadMQO()
\r
63 mqo = new MqoFile();
\r
69 private bool AutoBone_DoLoadRefTSO()
\r
72 tsor = LoadTSO(tsoref);
\r
74 foreach(TSOMesh i in tsor.meshes)
\r
75 foreach(TSOSubMesh j in i.sub)
\r
77 int[] bones = j.bones;
\r
79 for(int k= 0, n= j.numvertices; k < n; ++k)
\r
82 uint idx0= j.vertices[k].Idx;
\r
83 byte* idx = (byte*)(&idx0);
\r
84 idx[0] = (byte)bones[idx[0]];
\r
85 idx[1] = (byte)bones[idx[1]];
\r
86 idx[2] = (byte)bones[idx[2]];
\r
87 idx[3] = (byte)bones[idx[3]];
\r
88 j.vertices[k].Idx = idx0;
\r
92 CreatePointCluster(tsor);
\r
96 private bool OneBone_DoLoadRefTSO()
\r
99 tsor = LoadTSO(tsoref);
\r
103 private bool Common_DoLoadXml()
\r
106 ii = ImportInfo.Load(Path.ChangeExtension(mqoin, ".xml"));
\r
109 materials = new Dictionary<string, MaterialInfo>();
\r
110 bool validmap= true;
\r
112 foreach(MqoMaterial i in mqo.Materials)
\r
114 MaterialInfo mi = new MaterialInfo(dir, i, ii.GetMaterial(i.name));
\r
115 validmap &=mi.Valid;
\r
116 materials.Add(i.name, mi);
\r
119 if(!validmap || config.materialconfig)
\r
122 throw new Exception("マテリアルの設定が無効です");
\r
124 FormMaterial dlg = new FormMaterial();
\r
125 dlg.materials = materials;
\r
127 if(dlg.ShowDialog() != System.Windows.Forms.DialogResult.OK)
\r
132 textures = new Dictionary<string, TextureInfo>();
\r
134 foreach(MaterialInfo i in materials.Values)
\r
136 string name= Path.GetFileNameWithoutExtension(i.diffuse);
\r
138 if(!textures.ContainsKey(name))
\r
139 textures.Add(name, new TextureInfo(name, i.diffuse));
\r
141 name = Path.GetFileNameWithoutExtension(i.shadow);
\r
143 if(!textures.ContainsKey(name))
\r
144 textures.Add(name, new TextureInfo(name, i.shadow));
\r
150 private bool Common_DoWriteHeader()
\r
152 bw.Write(0x314F5354);
\r
156 private bool Common_DoWriteNodeNames()
\r
158 bw.Write(tsor.nodes.Length);
\r
160 nodes = new Dictionary<string,TSONode>();
\r
162 foreach(TSONode i in tsor.nodes)
\r
164 WriteString(bw, i.Name);
\r
165 nodes.Add(i.ShortName, i);
\r
171 private bool Common_DoWriteNodeMatrices()
\r
173 bw.Write(tsor.nodes.Length);
\r
175 foreach(TSONode i in tsor.nodes)
\r
176 WriteMatrix(bw, i.Matrix);
\r
181 private bool Common_DoWriteTextures()
\r
183 bw.Write(textures.Count);
\r
185 foreach(TextureInfo i in textures.Values)
\r
187 string file= i.file;
\r
188 string name= i.name;
\r
190 WriteString(bw, name);
\r
191 WriteString(bw, "\"" + Path.GetFileName(file) + "\"");
\r
194 TSOTex tex = LoadTex(file);
\r
196 bw.Write(tex.Width);
\r
197 bw.Write(tex.Height);
\r
198 bw.Write(tex.Depth);
\r
199 bw.Write(tex.data, 0, tex.data.Length);
\r
201 ImportTextureInfo iti = new ImportTextureInfo(tex);
\r
202 ii.textures.Add(iti);
\r
204 // テクスチャが同じフォルダにない場合、コピーしておく
\r
205 if(Path.GetDirectoryName(file).ToUpper() != dir.ToUpper())
\r
207 iti.File = Path.Combine(dir, Path.GetFileName(file));
\r
208 File.Copy(file, iti.File, true);
\r
215 private bool Common_DoWriteEffects()
\r
217 bw.Write(ii.effects.Count);
\r
219 foreach(ImportEffectInfo i in ii.effects)
\r
221 string file= Path.Combine(dir, i.Name);
\r
222 string[] code= File.ReadAllLines(file, Encoding.Default);
\r
224 WriteString(bw, i.Name);
\r
225 bw.Write(code.Length);
\r
227 foreach(string j in code)
\r
228 WriteString(bw, j.Trim('\r', '\n'));
\r
234 private bool Common_DoWriteMaterials()
\r
236 bw.Write(mqo.Materials.Count);
\r
238 foreach(MqoMaterial i in mqo.Materials)
\r
240 MaterialInfo mi = materials[i.name];
\r
241 string[] code= mi.GetCode();
\r
243 WriteString(bw, i.name);
\r
244 WriteString(bw, "cgfxShader");
\r
245 bw.Write(code.Length);
\r
247 foreach(string j in code)
\r
248 WriteString(bw, j.Trim('\r', '\n'));
\r
250 ImportMaterialInfo imi = new ImportMaterialInfo();
\r
252 imi.File = "cgfxShader";
\r
253 ii.materials.Add(imi);
\r
256 File.WriteAllLines(Path.Combine(dir, i.name), code);
\r
262 private bool AutoBone_DoGenerateMeshes()
\r
264 meshes = new List<TSOMesh>();
\r
266 foreach(MqoObject i in mqo.Objects)
\r
268 if(i.name.ToLower() == "bone")
\r
271 Console.WriteLine("object:" + i.name);
\r
274 List<int> vref= new List<int>(i.vertices.Count);
\r
276 foreach(Point3 j in i.vertices)
\r
277 vref.Add(pc.NearestIndex(j.x, j.y, j.z));
\r
280 Point3[] nrm = new Point3[i.vertices.Count];
\r
282 foreach(MqoFace j in i.faces)
\r
284 Point3 v1 = Point3.Normalize(i.vertices[j.b] - i.vertices[j.a]);
\r
285 Point3 v2 = Point3.Normalize(i.vertices[j.c] - i.vertices[j.b]);
\r
286 Point3 n = Point3.Normalize(Point3.Cross(v1, v2));
\r
293 for(int j= 0; j < nrm.Length; ++j)
\r
294 nrm[j] = Point3.Normalize(nrm[j]);
\r
297 List<int> faces1 = new List<int>();
\r
298 List<int> faces2 = new List<int>();
\r
299 //int[] bonecnv = new int[tsor.nodes.Length]; // ボーン変換テーブル
\r
300 VertexHeap<Vertex> vh = new VertexHeap<Vertex>();
\r
301 Vertex[] v = new Vertex[3];
\r
302 List<int> bones = new List<int>(16);
\r
303 List<ushort> indices = new List<ushort>();
\r
304 Dictionary<int, int> selected= new Dictionary<int,int>();
\r
305 Dictionary<int, int> work = new Dictionary<int,int>();
\r
306 List<TSOSubMesh> subs = new List<TSOSubMesh>();
\r
308 for(int j= 0, n= i.faces.Count; j < n; ++j)
\r
312 Console.WriteLine(" vertices bone_indices");
\r
313 Console.WriteLine(" -------- ------------");
\r
315 while (faces1.Count > 0)
\r
317 int mtl = i.faces[faces1[0]].mtl;
\r
323 foreach(int j in faces1)
\r
325 MqoFace f = i.faces[j];
\r
333 v[0] = vlst[vref[f.a]];
\r
334 v[1] = vlst[vref[f.b]];
\r
335 v[2] = vlst[vref[f.c]];
\r
339 for(int k= 0; k < 3; ++k)
\r
342 UInt32 idx0 = vv.Idx;
\r
343 Point4 wgt0 = vv.Wgt;
\r
344 byte* idx = (byte*)(&idx0);
\r
345 float* wgt = (float*)(&wgt0);
\r
347 for(int l= 0; l < 4; ++l)
\r
349 if(wgt[l] <= float.Epsilon) continue;
\r
350 if(selected.ContainsKey(idx[l])) continue;
\r
352 if(!work.ContainsKey(idx[l]))
\r
353 work.Add(idx[l], 0);
\r
357 if (selected.Count + work.Count > 16)
\r
364 foreach(KeyValuePair<int, int> l in work)
\r
366 selected.Add(l.Key, selected.Count); // ボーンテーブルに追加
\r
371 Vertex va = new Vertex(i.vertices[f.a], v[0].Wgt, v[0].Idx, nrm[f.a], new Point2(f.ta.x, 1-f.ta.y));
\r
372 Vertex vb = new Vertex(i.vertices[f.b], v[1].Wgt, v[1].Idx, nrm[f.b], new Point2(f.tb.x, 1-f.tb.y));
\r
373 Vertex vc = new Vertex(i.vertices[f.c], v[2].Wgt, v[2].Idx, nrm[f.c], new Point2(f.tc.x, 1-f.tc.y));
\r
375 indices.Add(vh.Add(va));
\r
376 indices.Add(vh.Add(vc));
\r
377 indices.Add(vh.Add(vb));
\r
381 ushort[] nidx = NvTriStrip.Optimize(indices.ToArray());
\r
384 Vertex[] verts = vh.verts.ToArray();
\r
386 for(int j= 0; j < verts.Length; ++j)
\r
388 uint idx0= verts[j].Idx;
\r
389 byte* idx = (byte*)(&idx0);
\r
390 Point4 wgt0= verts[j].Wgt;
\r
391 float* wgt = (float*)(&wgt0);
\r
393 for(int k= 0; k < 4; ++k)
\r
394 if(wgt[k] > float.Epsilon)
\r
395 idx[k] = (byte)selected[idx[k]];
\r
397 verts[j].Idx = idx0;
\r
401 TSOSubMesh sub = new TSOSubMesh();
\r
403 sub.numbones = bones.Count;
\r
404 sub.bones = bones.ToArray();
\r
405 sub.numvertices = nidx.Length;
\r
406 sub.vertices = new Vertex[nidx.Length];
\r
408 for(int j= 0; j < nidx.Length; ++j)
\r
409 sub.vertices[j] = verts[nidx[j]];
\r
411 Console.WriteLine(" {0,8} {1,12}", sub.vertices.Length, sub.bones.Length);
\r
416 List<int> t = faces1;
\r
423 TSOMesh mesh = new TSOMesh();
\r
424 mesh.name = i.name;
\r
425 mesh.numsubs = subs.Count;
\r
426 mesh.sub = subs.ToArray();
\r
427 mesh.matrix = Matrix44.Identity;
\r
435 private bool OneBone_DoGenerateMeshes()
\r
437 meshes = new List<TSOMesh>();
\r
439 foreach(MqoObject i in mqo.Objects)
\r
441 if(i.name.ToLower() == "bone")
\r
444 Console.WriteLine("object:" + i.name);
\r
447 Point3[] nrm = new Point3[i.vertices.Count];
\r
449 foreach(MqoFace j in i.faces)
\r
451 Point3 v1 = Point3.Normalize(i.vertices[j.b] - i.vertices[j.a]);
\r
452 Point3 v2 = Point3.Normalize(i.vertices[j.c] - i.vertices[j.b]);
\r
453 Point3 n = Point3.Normalize(Point3.Cross(v1, v2));
\r
459 for(int j= 0; j < nrm.Length; ++j)
\r
460 nrm[j] = Point3.Normalize(nrm[j]);
\r
463 uint idx = 0x00000000;
\r
464 Point4 wgt = new Point4(1, 0, 0, 0);
\r
465 int[] bones = new int[1];
\r
466 string bone = config.boneref[i.name];
\r
467 bones[0] = nodes[bone].ID;
\r
470 List<ushort> indices = new List<ushort>();
\r
471 VertexHeap<Vertex> vh = new VertexHeap<Vertex>();
\r
472 List<TSOSubMesh> subs = new List<TSOSubMesh>();
\r
474 for(int j= 0, n= materials.Count; j < n; ++j)
\r
479 foreach(MqoFace f in i.faces)
\r
484 Vertex va = new Vertex(i.vertices[f.a], wgt, idx, nrm[f.a], new Point2(f.ta.x, 1-f.ta.y));
\r
485 Vertex vb = new Vertex(i.vertices[f.b], wgt, idx, nrm[f.b], new Point2(f.tb.x, 1-f.tb.y));
\r
486 Vertex vc = new Vertex(i.vertices[f.c], wgt, idx, nrm[f.c], new Point2(f.tc.x, 1-f.tc.y));
\r
488 indices.Add(vh.Add(va));
\r
489 indices.Add(vh.Add(vc));
\r
490 indices.Add(vh.Add(vb));
\r
493 if(indices.Count == 0)
\r
497 ushort[] nidx = NvTriStrip.Optimize(indices.ToArray());
\r
500 Vertex[] verts= vh.verts.ToArray();
\r
501 TSOSubMesh sub = new TSOSubMesh();
\r
503 sub.numbones = bones.Length;
\r
505 sub.numvertices = nidx.Length;
\r
506 sub.vertices = new Vertex[nidx.Length];
\r
508 for(int k= 0; k < nidx.Length; ++k)
\r
509 sub.vertices[k] = verts[nidx[k]];
\r
515 TSOMesh mesh = new TSOMesh();
\r
516 mesh.name = i.name;
\r
517 mesh.numsubs = subs.Count;
\r
518 mesh.sub = subs.ToArray();
\r
519 mesh.matrix = Matrix44.Identity;
\r
527 private bool Common_DoWriteMeshes()
\r
529 bw.Write(meshes.Count);
\r
531 foreach(TSOMesh i in meshes)
\r
533 WriteString(bw, i.Name);
\r
534 WriteMatrix(bw, i.Matrix);
\r
536 bw.Write(i.numsubs);
\r
538 foreach(TSOSubMesh j in i.sub)
\r
541 bw.Write(j.numbones);
\r
543 foreach(int k in j.bones)
\r
546 bw.Write(j.numvertices);
\r
548 foreach(Vertex k in j.vertices)
\r
549 WriteVertex(bw, k);
\r
556 private bool AutoBone_DoOutput()
\r
558 //----- 出力処理 -----------------------------------------------
\r
559 ii.materials.Clear();
\r
560 ii.textures.Clear();
\r
562 using(FileStream fs= File.OpenWrite(tsoex))
\r
565 bw = new BinaryWriter(fs);
\r
567 Common_DoWriteHeader();
\r
568 Common_DoWriteNodeNames();
\r
569 Common_DoWriteNodeMatrices();
\r
570 Common_DoWriteTextures();
\r
571 Common_DoWriteEffects();
\r
572 Common_DoWriteMaterials();
\r
573 AutoBone_DoGenerateMeshes();
\r
574 Common_DoWriteMeshes();
\r
580 private bool OneBone_DoOutput()
\r
582 //----- 出力処理 -----------------------------------------------
\r
583 ii.materials.Clear();
\r
584 ii.textures.Clear();
\r
586 using(FileStream fs= File.OpenWrite(tsoex))
\r
589 bw = new BinaryWriter(fs);
\r
591 Common_DoWriteHeader();
\r
592 Common_DoWriteNodeNames();
\r
593 Common_DoWriteNodeMatrices();
\r
594 Common_DoWriteTextures();
\r
595 Common_DoWriteEffects();
\r
596 Common_DoWriteMaterials();
\r
597 OneBone_DoGenerateMeshes();
\r
598 Common_DoWriteMeshes();
\r
604 private bool Common_DoSaveXml()
\r
607 ImportInfo.Save(Path.ChangeExtension(mqoin, ".xml"), ii);
\r
611 private bool Common_DoCleanup()
\r
629 System.GC.Collect();
\r
633 public unsafe void GenerateOneBone(string mqoin, string tsoref, string tsoex, TSOGenerateConfig config)
\r
635 this.mqoin = mqoin;
\r
636 this.tsoref = tsoref;
\r
637 this.tsoex = tsoex;
\r
638 this.config = config;
\r
642 if(!Common_DoSetupDir()) return;
\r
643 if(!Common_DoLoadMQO()) return;
\r
644 if(!OneBone_DoLoadRefTSO()) return;
\r
645 if(!Common_DoLoadXml()) return;
\r
646 if(!OneBone_DoOutput()) return;
\r
647 if(!Common_DoSaveXml()) return;
\r
650 Common_DoCleanup();
\r
654 public unsafe void GenerateAutoBone(string mqoin, string tsoref, string tsoex, TSOGenerateConfig config)
\r
656 this.mqoin = mqoin;
\r
657 this.tsoref = tsoref;
\r
658 this.tsoex = tsoex;
\r
659 this.config = config;
\r
663 if(!Common_DoSetupDir()) return;
\r
664 if(!Common_DoLoadMQO()) return;
\r
665 if(!AutoBone_DoLoadRefTSO()) return;
\r
666 if(!Common_DoLoadXml()) return;
\r
667 if(!AutoBone_DoOutput()) return;
\r
668 if(!Common_DoSaveXml()) return;
\r
671 Common_DoCleanup();
\r
675 public void WriteString(BinaryWriter bw, string s)
\r
677 byte[] b = Encoding.Default.GetBytes(s);
\r
682 public void WriteMatrix(BinaryWriter bw, Matrix44 m)
\r
684 bw.Write(m.M11); bw.Write(m.M12); bw.Write(m.M13); bw.Write(m.M14);
\r
685 bw.Write(m.M21); bw.Write(m.M22); bw.Write(m.M23); bw.Write(m.M24);
\r
686 bw.Write(m.M31); bw.Write(m.M32); bw.Write(m.M33); bw.Write(m.M34);
\r
687 bw.Write(m.M41); bw.Write(m.M42); bw.Write(m.M43); bw.Write(m.M44);
\r
690 public unsafe void WriteVertex(BinaryWriter bw, Vertex v)
\r
693 byte* idx = (byte*)(&idx0);
\r
694 List<int> idxs = new List<int>(4);
\r
695 List<float> wgts = new List<float>(4);
\r
697 if(v.Wgt.x > 0) { idxs.Add(idx[0]); wgts.Add(v.Wgt.x); }
\r
698 if(v.Wgt.y > 0) { idxs.Add(idx[1]); wgts.Add(v.Wgt.y); }
\r
699 if(v.Wgt.z > 0) { idxs.Add(idx[2]); wgts.Add(v.Wgt.z); }
\r
700 if(v.Wgt.w > 0) { idxs.Add(idx[3]); wgts.Add(v.Wgt.w); }
\r
702 bw.Write(v.Pos.X); bw.Write(v.Pos.Y); bw.Write(v.Pos.Z);
\r
703 bw.Write(v.Nrm.X); bw.Write(v.Nrm.Y); bw.Write(v.Nrm.Z);
\r
704 bw.Write(v.Tex.X); bw.Write(v.Tex.Y);
\r
706 bw.Write(wgts.Count);
\r
708 for(int i= 0, n= idxs.Count; i < n; ++i)
\r
716 public TSOTex LoadTex(string file)
\r
718 string ext = Path.GetExtension(file).ToUpper();
\r
723 case ".TGA": tex= LoadTarga(file); break;
\r
724 case ".BMP": tex= LoadBitmap(file); break;
\r
725 default: throw new Exception("Unsupported texture file: " + file);
\r
728 for(int i= 0, n= tex.data.Length; i < n; i+=tex.Depth)
\r
730 byte b = tex.data[i+0];
\r
731 tex.data[i+0] = tex.data[i+2];
\r
738 public unsafe TSOTex LoadTarga(string file)
\r
740 using(FileStream fs= File.OpenRead(file))
\r
742 BinaryReader br = new BinaryReader(fs);
\r
743 TARGA_HEADER header;
\r
745 Marshal.Copy(br.ReadBytes(sizeof(TARGA_HEADER)), 0, (IntPtr)(&header), sizeof(TARGA_HEADER));
\r
747 if(header.imagetype != 0x02) throw new Exception("Invalid imagetype: " + file);
\r
748 if(header.depth != 24
\r
749 && header.depth != 32) throw new Exception("Invalid depth: " + file);
\r
751 TSOTex tex = new TSOTex();
\r
752 tex.depth = header.depth / 8;
\r
753 tex.width = header.width;
\r
754 tex.height = header.height;
\r
756 tex.data = br.ReadBytes(tex.width * tex.height * tex.depth);
\r
762 public unsafe TSOTex LoadBitmap(string file)
\r
764 using(FileStream fs= File.OpenRead(file))
\r
766 BinaryReader br = new BinaryReader(fs);
\r
767 BITMAPFILEHEADER bfh;
\r
768 BITMAPINFOHEADER bih;
\r
770 Marshal.Copy(br.ReadBytes(sizeof(BITMAPFILEHEADER)), 0, (IntPtr)(&bfh), sizeof(BITMAPFILEHEADER));
\r
771 Marshal.Copy(br.ReadBytes(sizeof(BITMAPINFOHEADER)), 0, (IntPtr)(&bih), sizeof(BITMAPINFOHEADER));
\r
773 if(bfh.bfType != 0x4D42) throw new Exception("Invalid imagetype: " + file);
\r
774 if(bih.biBitCount != 24
\r
775 && bih.biBitCount != 32) throw new Exception("Invalid depth: " + file);
\r
777 TSOTex tex = new TSOTex();
\r
778 tex.depth = bih.biBitCount / 8;
\r
779 tex.width = bih.biWidth;
\r
780 tex.height = bih.biHeight;
\r
782 tex.data = br.ReadBytes(tex.width * tex.height * tex.depth);
\r
790 public class TextureInfo
\r
792 public string name;
\r
793 public string file;
\r
795 public TextureInfo(string name, string file)
\r
802 public class MaterialInfo
\r
804 public string name;
\r
805 public string shader;
\r
806 public string diffuse;
\r
807 public string shadow;
\r
808 //public Dictionary<string, string> parameters;
\r
810 public MaterialInfo(string path, MqoMaterial mqom, ImportMaterialInfo impm)
\r
813 diffuse = mqom.tex;
\r
817 string file= Path.Combine(path, impm.Name);
\r
819 if(File.Exists(file))
\r
822 if(impm.shadow != null)
\r
824 file = Path.Combine(path, impm.shadow.File);
\r
826 if(File.Exists(file))
\r
836 return File.Exists(shader)
\r
837 && File.Exists(diffuse)
\r
838 && File.Exists(shadow);
\r
842 public string[] GetCode()
\r
844 TSOMaterialCode code= TSOMaterialCode.GenerateFromFile(shader);
\r
845 List<string> line= new List<string>();
\r
847 code.SetValue("ColorTex", Path.GetFileNameWithoutExtension(diffuse));
\r
848 code.SetValue("ShadeTex", Path.GetFileNameWithoutExtension(shadow));
\r
850 foreach(KeyValuePair<string, TSOParameter> i in code)
\r
851 line.Add(i.Value.ToString());
\r
853 return line.ToArray();
\r
856 public string Name { get { return name; } }
\r
858 [Editor(typeof(FileNameEditor), typeof(UITypeEditor))]
\r
859 [DisplayNameAttribute("シェーダー設定ファイル")]
\r
860 public string ShaderFile { get { return shader; } set { shader = value; } }
\r
862 [Editor(typeof(FileNameEditor), typeof(UITypeEditor))]
\r
863 [DisplayNameAttribute("テクスチャ:カラー")]
\r
864 public string DiffuseTexture { get { return diffuse; } set { diffuse = value; } }
\r
866 [Editor(typeof(FileNameEditor), typeof(UITypeEditor))]
\r
867 [DisplayNameAttribute("テクスチャ:シェーティング")]
\r
868 public string ShadowTexture { get { return shadow; } set { shadow = value; } }
\r