OSDN Git Service

7ca74eaa8ed6301396ee3d65ff1a57d654159b6a
[tdcgexplorer/tso2mqo.git] / Form1.cs
1 using System;
2 using System.Collections.Generic;
3 using System.ComponentModel;
4 using System.Data;
5 using System.Drawing;
6 using System.IO;
7 using System.Text;
8 using System.Windows.Forms;
9 using Microsoft.Win32;
10
11 namespace Tso2MqoGui
12 {
13     public partial class Form1 : Form
14     {
15         public Form1()
16         {
17             InitializeComponent();
18         }
19
20         private void Form1_Load(object sender, EventArgs e)
21         {
22             RegistryKey reg = Application.UserAppDataRegistry.CreateSubKey("Config");
23             tbPath.Text = (string)reg.GetValue("OutPath", Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments));
24             tabControl1.SelectedIndex = (int)reg.GetValue("TabPage", 0);
25             tbMqoFile.Text = (string)reg.GetValue("MqoIn", "");
26             tbTsoFileRef.Text = (string)reg.GetValue("Tso", "");
27             tbTsoFile.Text = (string)reg.GetValue("TsoEx", "");
28             tbMergeTso.Text = (string)reg.GetValue("MergeTso", "");
29             rbRefBone.Checked = (int)reg.GetValue("RefBone", 1) == 1;
30             rbOneBone.Checked = (int)reg.GetValue("OneBone", 0) == 1;
31             rbBoneNone.Checked = (int)reg.GetValue("BoneNone", 1) == 1;
32             rbBoneRokDeBone.Checked = (int)reg.GetValue("BoneRokDeBone", 0) == 1;
33             cbMakeSub.Checked = (int)reg.GetValue("MakeSub", 1) == 1;
34             cbCopyTSO.Checked = (int)reg.GetValue("CopyTSO", 1) == 1;
35             cbShowMaterials.Checked = (int)reg.GetValue("ShowMaterials", 0) == 1;
36
37             reg = Application.UserAppDataRegistry.CreateSubKey("Form1");
38             Bounds = new Rectangle(
39                 (int)reg.GetValue("Left", 0),
40                 (int)reg.GetValue("Top", 0),
41                 (int)reg.GetValue("Width", 640),
42                 (int)reg.GetValue("Height", 320));
43
44             EnableControlStuff();
45
46             Config config = Config.Instance;
47         }
48
49         private void Form1_FormClosed(object sender, FormClosedEventArgs e)
50         {
51             RegistryKey reg = Application.UserAppDataRegistry.CreateSubKey("Config");
52             reg.SetValue("OutPath", tbPath.Text);
53             reg.SetValue("TabPage", tabControl1.SelectedIndex);
54             reg.SetValue("MqoIn", tbMqoFile.Text);
55             reg.SetValue("Tso", tbTsoFileRef.Text);
56             reg.SetValue("TsoEx", tbTsoFile.Text);
57             reg.SetValue("MergeTso", tbMergeTso.Text);
58             reg.SetValue("RefBone", rbRefBone.Checked ? 1 : 0);
59             reg.SetValue("OneBone", rbOneBone.Checked ? 1 : 0);
60             reg.SetValue("BoneNone", rbBoneNone.Checked ? 1 : 0);
61             reg.SetValue("BoneRokDeBone", rbBoneRokDeBone.Checked ? 1 : 0);
62             reg.SetValue("MakeSub", cbMakeSub.Checked ? 1 : 0);
63             reg.SetValue("CopyTSO", cbCopyTSO.Checked ? 1 : 0);
64             reg.SetValue("ShowMaterials", cbShowMaterials.Checked ? 1 : 0);
65
66             reg = Application.UserAppDataRegistry.CreateSubKey("Form1");
67
68             if ((this.WindowState & FormWindowState.Minimized) == FormWindowState.Minimized)
69             {
70                 reg.SetValue("Top", RestoreBounds.Top);
71                 reg.SetValue("Left", RestoreBounds.Left);
72                 reg.SetValue("Width", RestoreBounds.Width);
73                 reg.SetValue("Height", RestoreBounds.Height);
74             }
75             else
76             {
77                 reg.SetValue("Top", Top);
78                 reg.SetValue("Left", Left);
79                 reg.SetValue("Width", Width);
80                 reg.SetValue("Height", Height);
81             }
82
83             Config.Save();
84         }
85
86         private void Form1_DragDrop(object sender, DragEventArgs e)
87         {
88             try
89             {
90                 if (!e.Data.GetDataPresent(DataFormats.FileDrop))
91                     return;
92
93                 string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
94
95                 if (files.Length == 0)
96                     return;
97
98                 switch (tabControl1.SelectedIndex)
99                 {
100                     case 0:
101                         foreach (string i in files)
102                         {
103                             if (Path.GetExtension(i).ToUpper() == ".TSO")
104                                 GenerateMqo(i);
105                         }
106
107                         break;
108
109                     case 1:
110                         switch (Path.GetExtension(files[0]).ToUpper())
111                         {
112                             case ".TSO": tbTsoFileRef.Text = files[0]; break;
113                             case ".MQO": tbMqoFile.Text = files[0]; break;
114                         }
115
116                         break;
117
118                     case 2:
119                         AddMergeTso(files);
120                         break;
121                 }
122             }
123             catch (Exception exception)
124             {
125                 Util.ProcessError(exception);
126             }
127         }
128
129         private void Form1_DragEnter(object sender, DragEventArgs e)
130         {
131             if (!e.Data.GetDataPresent(DataFormats.FileDrop))
132                 return;
133
134             e.Effect = DragDropEffects.Copy;
135         }
136
137         private void tbMergeTso_DragDrop(object sender, DragEventArgs e)
138         {
139             if (!e.Data.GetDataPresent(DataFormats.FileDrop))
140                 return;
141
142             string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
143
144             switch (Path.GetExtension(files[0]).ToUpper())
145             {
146                 case ".TSO": tbMergeTso.Text = files[0]; break;
147             }
148         }
149
150         private void tbMergeTso_DragEnter(object sender, DragEventArgs e)
151         {
152             if (!e.Data.GetDataPresent(DataFormats.FileDrop))
153                 return;
154
155             e.Effect = DragDropEffects.Copy;
156         }
157
158         private void GenerateMqo(string tso_file)
159         {
160             string out_path = tbPath.Text;
161
162             if (cbMakeSub.Checked)
163             {
164                 out_path = Path.Combine(out_path, Path.GetFileNameWithoutExtension(tso_file));
165                 Directory.CreateDirectory(out_path);
166             }
167
168             try
169             {
170                 label2.BackColor = Color.Tomato;
171                 label2.ForeColor = Color.White;
172                 label2.Text = "Processing";
173                 label2.Invalidate();
174                 label2.Update();
175
176                 MqoGenerator gen = new MqoGenerator();
177                 gen.Generate(tso_file, out_path, rbBoneRokDeBone.Checked);
178
179                 if (cbCopyTSO.Checked)
180                 {
181                     string tso_path = Path.Combine(out_path, Path.GetFileName(tso_file));
182
183                     if (tso_file != tso_path)
184                         File.Copy(tso_file, tso_path, true);
185                 }
186             }
187             finally
188             {
189                 label2.BackColor = SystemColors.Control;
190                 label2.BackColor = label2.Parent.BackColor;
191                 label2.ForeColor = SystemColors.ControlText;
192                 label2.Text = "Drop TSO File Here!";
193             }
194         }
195
196         private void GenerateTso(string file)
197         {
198             TSOGeneratorConfig config = new TSOGeneratorConfig();
199             config.ShowMaterials = cbShowMaterials.Checked;
200
201             if (rbRefBone.Checked)
202             {
203                 TSOGeneratorMqxBone gen = new TSOGeneratorMqxBone(config);
204                 gen.Generate(file, tbTsoFileRef.Text, tbTsoFile.Text);
205             }
206             else if (rbOneBone.Checked)
207             {
208                 TSOGeneratorOneBone gen = new TSOGeneratorOneBone(config);
209
210                 foreach (ListViewItem item in lvObjects.Items)
211                 {
212                     if (item.SubItems[1].Text == "")
213                     {
214                         MessageBox.Show("すべてのオブジェクトにボーンを設定してください");
215                         return;
216                     }
217
218                     gen.ObjectBoneNames.Add(item.SubItems[0].Text, item.SubItems[1].Text);
219                 }
220
221                 gen.Generate(file, tbTsoFileRef.Text, tbTsoFile.Text);
222             }
223         }
224         #region tso->mqo UI
225         private void button1_Click(object sender, EventArgs e)
226         {
227             FolderBrowserDialog dlg = new FolderBrowserDialog();
228             dlg.SelectedPath = tbPath.Text;
229
230             if (dlg.ShowDialog() == DialogResult.OK)
231                 tbPath.Text = dlg.SelectedPath;
232         }
233         #endregion
234         #region mqo->tso UI
235         private void radioButton1_CheckedChanged(object sender, EventArgs e)
236         {
237             EnableControlStuff();
238         }
239
240         private void radioButton2_CheckedChanged(object sender, EventArgs e)
241         {
242             EnableControlStuff();
243         }
244
245         private void EnableControlStuff()
246         {
247             gbBone.Enabled = rbOneBone.Checked;
248         }
249
250         private void BuildBoneTree(TreeNodeCollection nodes, TSONode node)
251         {
252             TreeNode tn = nodes.Add(node.ShortName);
253             tn.Tag = node;
254
255             if (node.children != null)
256                 foreach (TSONode i in node.children)
257                     BuildBoneTree(tn.Nodes, i);
258         }
259
260         private void SaveAssign()
261         {
262             foreach (ListViewItem item in lvObjects.Items)
263             {
264                 string obj = item.SubItems[0].Text;
265                 string bone = item.SubItems[1].Text;
266
267                 if (Config.Instance.object_bone_map.ContainsKey(obj))
268                     Config.Instance.object_bone_map[obj] = bone;
269                 else
270                     Config.Instance.object_bone_map.Add(obj, bone);
271             }
272         }
273
274         private void btnMqoFile_Click(object sender, EventArgs e)
275         {
276             try
277             {
278                 OpenFileDialog dlg = new OpenFileDialog();
279                 dlg.Filter = "Metasequoia File (*.mqo)|*.mqo";
280                 dlg.FileName = tbMqoFile.Text;
281
282                 if (dlg.ShowDialog() == DialogResult.OK)
283                     tbMqoFile.Text = dlg.FileName;
284             }
285             catch (Exception exception)
286             {
287                 Util.ProcessError(exception);
288             }
289         }
290
291         private void btnTsoFileRef_Click(object sender, EventArgs e)
292         {
293             try
294             {
295                 OpenFileDialog dlg = new OpenFileDialog();
296                 dlg.Filter = "TSO File (*.tso)|*.tso";
297                 dlg.FileName = tbTsoFileRef.Text;
298
299                 if (dlg.ShowDialog() == DialogResult.OK)
300                     tbTsoFileRef.Text = dlg.FileName;
301             }
302             catch (Exception exception)
303             {
304                 Util.ProcessError(exception);
305             }
306         }
307
308         private void btnTsoFile_Click(object sender, EventArgs e)
309         {
310             try
311             {
312                 SaveFileDialog dlg = new SaveFileDialog();
313                 dlg.Filter = "TSO File (*.tso)|*.tso";
314                 dlg.FileName = tbTsoFile.Text;
315
316                 if (dlg.ShowDialog() == DialogResult.OK)
317                     tbTsoFile.Text = dlg.FileName;
318             }
319             catch (Exception exception)
320             {
321                 Util.ProcessError(exception);
322             }
323         }
324
325         private void btnRefresh_Click(object sender, EventArgs e)
326         {
327             try
328             {
329                 // 一旦現状を保存
330                 SaveAssign();
331
332                 // オブジェクト
333                 MqoReader mqo = new MqoReader();
334                 mqo.Load(tbMqoFile.Text);
335                 lvObjects.Items.Clear();
336
337                 foreach (MqoObject obj in mqo.Objects)
338                 {
339                     ListViewItem item = lvObjects.Items.Add(obj.name);
340                     item.Tag = obj;
341                     string bone;
342
343                     if (Config.Instance.object_bone_map.TryGetValue(obj.name, out bone))
344                         item.SubItems.Add(bone);
345                     else
346                         item.SubItems.Add("");
347                 }
348
349                 // ボーン構造
350                 TSOFile tso = new TSOFile(tbTsoFileRef.Text);
351                 tso.ReadAll();
352                 tvBones.Visible = false;
353                 tvBones.Nodes.Clear();
354                 BuildBoneTree(tvBones.Nodes, tso.nodes[0]);
355                 tvBones.ExpandAll();
356                 tvBones.Nodes[0].EnsureVisible();
357             }
358             catch (Exception exception)
359             {
360                 Util.ProcessError(exception);
361             }
362             finally
363             {
364                 tvBones.Visible = true;
365             }
366         }
367
368         private void btnSelectAll_Click(object sender, EventArgs e)
369         {
370             foreach (ListViewItem item in lvObjects.Items)
371                 item.Selected = true;
372         }
373
374         private void btnDeselectAll_Click(object sender, EventArgs e)
375         {
376             foreach (ListViewItem item in lvObjects.Items)
377                 item.Selected = false;
378         }
379
380         private void btnAssign_Click(object sender, EventArgs e)
381         {
382             try
383             {
384                 TreeNode node = tvBones.SelectedNode;
385
386                 if (node == null)
387                 {
388                     MessageBox.Show("割り当てるボーンを選択してください");
389                     return;
390                 }
391
392                 foreach (ListViewItem item in lvObjects.SelectedItems)
393                     item.SubItems[1].Text = node.Text;
394
395                 SaveAssign();
396             }
397             catch (Exception ex)
398             {
399                 Util.ProcessError(ex);
400             }
401         }
402
403         private void btnGenerate_Click(object sender, EventArgs e)
404         {
405             Color c = tabPage2.BackColor;
406
407             try
408             {
409                 tabPage2.BackColor = Color.Tomato;
410                 tabPage2.Update();
411                 string file = tbMqoFile.Text;
412                 GenerateTso(file);
413             }
414             catch (Exception exception)
415             {
416                 Util.ProcessError(exception);
417             }
418             finally
419             {
420                 tabPage2.BackColor = c;
421             }
422         }
423         #endregion
424         #region Merge UI
425         private void AddMergeTso(string[] files)
426         {
427             foreach (string file in files)
428             {
429                 if (Path.GetExtension(files[0]).ToUpper() != ".TSO")
430                     continue;
431
432                 if (tvMerge.Nodes.Find(file, false).Length == 0)
433                 {
434                     TreeNode node = tvMerge.Nodes.Add(file);
435                     node.Name = file;
436                     node.Checked = true;
437
438                     TSOFile tso = new TSOFile(file);
439                     tso.ReadAll();
440
441                     foreach (TSOMesh j in tso.meshes)
442                     {
443                         TreeNode mesh = node.Nodes.Add(j.Name);
444                         mesh.Name = j.Name;
445                         mesh.Checked = true;
446                     }
447                 }
448             }
449         }
450
451         private void btnMerge_Click(object sender, EventArgs e)
452         {
453             Color c = tabPage2.BackColor;
454
455             try
456             {
457                 tabPage2.BackColor = Color.Tomato;
458                 List<TSOMesh> meshes = new List<TSOMesh>();
459                 Dictionary<string, Pair<TSOMaterial, int>> materialmap = new Dictionary<string, Pair<TSOMaterial, int>>();
460                 Dictionary<string, TSOTex> textures = new Dictionary<string, TSOTex>();
461                 TSOFile last = null;
462
463                 foreach (TreeNode node in tvMerge.Nodes)
464                 {
465                     TSOFile tso = new TSOFile(node.Text);
466                     last = tso;
467                     ulong mtls = 0;
468                     ulong mask = 1;
469                     tso.ReadAll();
470
471                     foreach (TSOMesh mesh in tso.meshes)
472                     {
473                         TreeNode[] found = node.Nodes.Find(mesh.Name, false);
474
475                         if (found.Length == 0 || !found[0].Checked)
476                             continue;
477
478                         foreach (TSOSubMesh k in mesh.sub_meshes)
479                             mtls |= 1ul << k.spec;
480
481                         meshes.Add(mesh);
482                     }
483
484                     foreach (TSOMaterial mat in tso.materials)
485                     {
486                         if ((mask & mtls) != 0)
487                         {
488                             if (!materialmap.ContainsKey(mat.Name))
489                             {
490                                 Pair<TSOMaterial, int> value = new Pair<TSOMaterial, int>(mat, materialmap.Count);
491                                 materialmap.Add(mat.Name, value);
492
493                                 if (!textures.ContainsKey(mat.ColorTex))
494                                 {
495                                     TSOTex tex = tso.texturemap[mat.ColorTex];
496                                     textures.Add(tex.Name, tex);
497                                 }
498
499                                 if (!textures.ContainsKey(mat.ShadeTex))
500                                 {
501                                     TSOTex tex = tso.texturemap[mat.ShadeTex];
502                                     textures.Add(tex.Name, tex);
503                                 }
504                             }
505                         }
506
507                         mask <<= 1;
508                     }
509                 }
510
511                 using (FileStream fs = File.OpenWrite(tbMergeTso.Text))
512                 {
513                     fs.SetLength(0);
514
515                     List<TSOTex> texlist = new List<TSOTex>(textures.Values);
516                     TSOMaterial[] mtllist = new TSOMaterial[materialmap.Count];
517
518                     foreach (var i in materialmap.Values)
519                         mtllist[i.Second] = i.First;
520
521                     foreach (TSOMesh mesh in meshes)
522                     {
523                         foreach (TSOSubMesh sub in mesh.sub_meshes)
524                         {
525                             TSOMaterial spec = mesh.file.materials[sub.spec];
526                             sub.spec = materialmap[spec.Name].Second;
527                         }
528                     }
529
530                     foreach (TSOTex tex in texlist)
531                         TSOFile.ExchangeChannel(tex.data, tex.depth);
532
533                     BinaryWriter bw = new BinaryWriter(fs);
534                     TSOWriter.WriteHeader(bw);
535                     TSOWriter.Write(bw, last.nodes);
536                     TSOWriter.Write(bw, texlist.ToArray());
537                     TSOWriter.Write(bw, last.effects);
538                     TSOWriter.Write(bw, mtllist);
539                     TSOWriter.Write(bw, meshes.ToArray());
540                 }
541             }
542             catch (Exception exception)
543             {
544                 Util.ProcessError(exception);
545             }
546             finally
547             {
548                 tabPage2.BackColor = c;
549             }
550         }
551
552         private void btnMergeAdd_Click(object sender, EventArgs e)
553         {
554             try
555             {
556                 OpenFileDialog dlg = new OpenFileDialog();
557                 dlg.Filter = "TSO File(*.tso)|*.tso";
558                 dlg.Multiselect = true;
559
560                 if (dlg.ShowDialog() == DialogResult.OK)
561                     AddMergeTso(dlg.FileNames);
562             }
563             catch (Exception exception)
564             {
565                 Util.ProcessError(exception);
566             }
567         }
568
569         private void btnMergeDel_Click(object sender, EventArgs e)
570         {
571             if (tvMerge.SelectedNode != null && tvMerge.SelectedNode.Level == 0)
572                 tvMerge.SelectedNode.Remove();
573         }
574
575         private void btnMergeReset_Click(object sender, EventArgs e)
576         {
577             tvMerge.Nodes.Clear();
578         }
579
580         private void btnRefMergeTso_Click(object sender, EventArgs e)
581         {
582             try
583             {
584                 SaveFileDialog dlg = new SaveFileDialog();
585                 dlg.Filter = "TSO File (*.tso)|*.tso";
586                 dlg.FileName = tbMergeTso.Text;
587
588                 if (dlg.ShowDialog() == DialogResult.OK)
589                     tbMergeTso.Text = dlg.FileName;
590             }
591             catch (Exception exception)
592             {
593                 Util.ProcessError(exception);
594             }
595         }
596
597         public static bool bTvMerge_AfterCheck = false;
598
599         private void tvMerge_AfterCheck(object sender, TreeViewEventArgs e)
600         {
601             if (bTvMerge_AfterCheck)
602                 return;
603
604             bTvMerge_AfterCheck = true;
605
606             try
607             {
608                 if (e.Node.Level == 0)
609                 {
610                     foreach (TreeNode node in e.Node.Nodes)
611                         node.Checked = e.Node.Checked;
612                 }
613                 else
614                 {
615                     bool check = false;
616
617                     foreach (TreeNode node in e.Node.Parent.Nodes)
618                         if (node.Checked) check = true;
619
620                     e.Node.Parent.Checked = check;
621                 }
622             }
623             finally
624             {
625                 bTvMerge_AfterCheck = false;
626             }
627         }
628         #endregion
629     }
630
631     public class Util
632     {
633         public static void ProcessError(Exception exception)
634         {
635             MessageBox.Show(exception.ToString());
636         }
637     }
638 }