OSDN Git Service

29ad540df889bbd62e1d3d0b25e40f288cf92187
[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                 if (tbTsoFileRef.Text == "")
204                 {
205                     TSOGeneratorMqxBone gen = new TSOGeneratorMqxBone(config);
206                     gen.Generate(file, tbTsoFileRef.Text, tbTsoFile.Text);
207                 }
208                 else
209                 {
210                     TSOGeneratorRefBone gen = new TSOGeneratorRefBone(config);
211                     gen.Generate(file, tbTsoFileRef.Text, tbTsoFile.Text);
212                 }
213             }
214             else if (rbOneBone.Checked)
215             {
216                 TSOGeneratorOneBone gen = new TSOGeneratorOneBone(config);
217
218                 foreach (ListViewItem item in lvObjects.Items)
219                 {
220                     if (item.SubItems[1].Text == "")
221                     {
222                         MessageBox.Show("すべてのオブジェクトにボーンを設定してください");
223                         return;
224                     }
225
226                     gen.ObjectBoneNames.Add(item.SubItems[0].Text, item.SubItems[1].Text);
227                 }
228
229                 gen.Generate(file, tbTsoFileRef.Text, tbTsoFile.Text);
230             }
231         }
232         #region tso->mqo UI
233         private void button1_Click(object sender, EventArgs e)
234         {
235             FolderBrowserDialog dlg = new FolderBrowserDialog();
236             dlg.SelectedPath = tbPath.Text;
237
238             if (dlg.ShowDialog() == DialogResult.OK)
239                 tbPath.Text = dlg.SelectedPath;
240         }
241         #endregion
242         #region mqo->tso UI
243         private void radioButton1_CheckedChanged(object sender, EventArgs e)
244         {
245             EnableControlStuff();
246         }
247
248         private void radioButton2_CheckedChanged(object sender, EventArgs e)
249         {
250             EnableControlStuff();
251         }
252
253         private void EnableControlStuff()
254         {
255             gbBone.Enabled = rbOneBone.Checked;
256         }
257
258         private void BuildBoneTree(TreeNodeCollection nodes, TSONode node)
259         {
260             TreeNode tn = nodes.Add(node.Name);
261             tn.Tag = node;
262
263             if (node.children != null)
264                 foreach (TSONode i in node.children)
265                     BuildBoneTree(tn.Nodes, i);
266         }
267
268         private void SaveAssign()
269         {
270             foreach (ListViewItem item in lvObjects.Items)
271             {
272                 string obj = item.SubItems[0].Text;
273                 string bone = item.SubItems[1].Text;
274
275                 if (Config.Instance.object_bone_map.ContainsKey(obj))
276                     Config.Instance.object_bone_map[obj] = bone;
277                 else
278                     Config.Instance.object_bone_map.Add(obj, bone);
279             }
280         }
281
282         private void btnMqoFile_Click(object sender, EventArgs e)
283         {
284             try
285             {
286                 OpenFileDialog dlg = new OpenFileDialog();
287                 dlg.Filter = "Metasequoia File (*.mqo)|*.mqo";
288                 dlg.FileName = tbMqoFile.Text;
289
290                 if (dlg.ShowDialog() == DialogResult.OK)
291                     tbMqoFile.Text = dlg.FileName;
292             }
293             catch (Exception exception)
294             {
295                 Util.ProcessError(exception);
296             }
297         }
298
299         private void btnTsoFileRef_Click(object sender, EventArgs e)
300         {
301             try
302             {
303                 OpenFileDialog dlg = new OpenFileDialog();
304                 dlg.Filter = "TSO File (*.tso)|*.tso";
305                 dlg.FileName = tbTsoFileRef.Text;
306
307                 if (dlg.ShowDialog() == DialogResult.OK)
308                     tbTsoFileRef.Text = dlg.FileName;
309             }
310             catch (Exception exception)
311             {
312                 Util.ProcessError(exception);
313             }
314         }
315
316         private void btnTsoFile_Click(object sender, EventArgs e)
317         {
318             try
319             {
320                 SaveFileDialog dlg = new SaveFileDialog();
321                 dlg.Filter = "TSO File (*.tso)|*.tso";
322                 dlg.FileName = tbTsoFile.Text;
323
324                 if (dlg.ShowDialog() == DialogResult.OK)
325                     tbTsoFile.Text = dlg.FileName;
326             }
327             catch (Exception exception)
328             {
329                 Util.ProcessError(exception);
330             }
331         }
332
333         private void btnRefresh_Click(object sender, EventArgs e)
334         {
335             try
336             {
337                 // 一旦現状を保存
338                 SaveAssign();
339
340                 // オブジェクト
341                 MqoReader mqo = new MqoReader();
342                 mqo.Load(tbMqoFile.Text);
343
344                 lvObjects.Items.Clear();
345                 foreach (MqoObject obj in mqo.Objects)
346                 {
347                     ListViewItem item = lvObjects.Items.Add(obj.name);
348                     item.Tag = obj;
349                     string bone;
350
351                     if (Config.Instance.object_bone_map.TryGetValue(obj.name, out bone))
352                         item.SubItems.Add(bone);
353                     else
354                         item.SubItems.Add("");
355                 }
356
357                 // ボーン構造
358                 TSOFile tso = new TSOFile();
359                 tso.Load(tbTsoFileRef.Text);
360                 tvBones.Visible = false;
361                 tvBones.Nodes.Clear();
362                 BuildBoneTree(tvBones.Nodes, tso.nodes[0]);
363                 tvBones.ExpandAll();
364                 tvBones.Nodes[0].EnsureVisible();
365             }
366             catch (Exception exception)
367             {
368                 Util.ProcessError(exception);
369             }
370             finally
371             {
372                 tvBones.Visible = true;
373             }
374         }
375
376         private void btnSelectAll_Click(object sender, EventArgs e)
377         {
378             foreach (ListViewItem item in lvObjects.Items)
379                 item.Selected = true;
380         }
381
382         private void btnDeselectAll_Click(object sender, EventArgs e)
383         {
384             foreach (ListViewItem item in lvObjects.Items)
385                 item.Selected = false;
386         }
387
388         private void btnAssign_Click(object sender, EventArgs e)
389         {
390             try
391             {
392                 TreeNode node = tvBones.SelectedNode;
393
394                 if (node == null)
395                 {
396                     MessageBox.Show("割り当てるボーンを選択してください");
397                     return;
398                 }
399
400                 foreach (ListViewItem item in lvObjects.SelectedItems)
401                     item.SubItems[1].Text = node.Text;
402
403                 SaveAssign();
404             }
405             catch (Exception ex)
406             {
407                 Util.ProcessError(ex);
408             }
409         }
410
411         private void btnGenerate_Click(object sender, EventArgs e)
412         {
413             Color c = tabPage2.BackColor;
414
415             try
416             {
417                 tabPage2.BackColor = Color.Tomato;
418                 tabPage2.Update();
419                 string file = tbMqoFile.Text;
420                 GenerateTso(file);
421             }
422             catch (Exception exception)
423             {
424                 Util.ProcessError(exception);
425             }
426             finally
427             {
428                 tabPage2.BackColor = c;
429             }
430         }
431         #endregion
432         #region Merge UI
433         private void AddMergeTso(string[] files)
434         {
435             foreach (string file in files)
436             {
437                 if (Path.GetExtension(files[0]).ToUpper() != ".TSO")
438                     continue;
439
440                 if (tvMerge.Nodes.Find(file, false).Length == 0)
441                 {
442                     TreeNode node = tvMerge.Nodes.Add(file);
443                     node.Name = file;
444                     node.Checked = true;
445
446                     TSOFile tso = new TSOFile();
447                     tso.Load(file);
448
449                     foreach (TSOMesh j in tso.meshes)
450                     {
451                         TreeNode mesh = node.Nodes.Add(j.Name);
452                         mesh.Name = j.Name;
453                         mesh.Checked = true;
454                     }
455                 }
456             }
457         }
458
459         private void btnMerge_Click(object sender, EventArgs e)
460         {
461             Color c = tabPage2.BackColor;
462
463             try
464             {
465                 tabPage2.BackColor = Color.Tomato;
466                 List<TSOMesh> meshes = new List<TSOMesh>();
467                 Dictionary<string, Pair<TSOMaterial, int>> materialmap = new Dictionary<string, Pair<TSOMaterial, int>>();
468                 Dictionary<string, TSOTex> textures = new Dictionary<string, TSOTex>();
469                 TSOFile last = null;
470
471                 foreach (TreeNode node in tvMerge.Nodes)
472                 {
473                     TSOFile tso = new TSOFile();
474                     last = tso;
475                     ulong mtls = 0;
476                     ulong mask = 1;
477                     tso.Load(node.Text);
478
479                     foreach (TSOMesh mesh in tso.meshes)
480                     {
481                         TreeNode[] found = node.Nodes.Find(mesh.Name, false);
482
483                         if (found.Length == 0 || !found[0].Checked)
484                             continue;
485
486                         foreach (TSOSubMesh k in mesh.sub_meshes)
487                             mtls |= 1ul << k.spec;
488
489                         meshes.Add(mesh);
490                     }
491
492                     foreach (TSOMaterial mat in tso.materials)
493                     {
494                         if ((mask & mtls) != 0)
495                         {
496                             if (!materialmap.ContainsKey(mat.Name))
497                             {
498                                 Pair<TSOMaterial, int> value = new Pair<TSOMaterial, int>(mat, materialmap.Count);
499                                 materialmap.Add(mat.Name, value);
500
501                                 if (!textures.ContainsKey(mat.ColorTex))
502                                 {
503                                     TSOTex tex = tso.texturemap[mat.ColorTex];
504                                     textures.Add(tex.Name, tex);
505                                 }
506
507                                 if (!textures.ContainsKey(mat.ShadeTex))
508                                 {
509                                     TSOTex tex = tso.texturemap[mat.ShadeTex];
510                                     textures.Add(tex.Name, tex);
511                                 }
512                             }
513                         }
514
515                         mask <<= 1;
516                     }
517                 }
518
519                 using (FileStream fs = File.OpenWrite(tbMergeTso.Text))
520                 {
521                     fs.SetLength(0);
522
523                     List<TSOTex> texlist = new List<TSOTex>(textures.Values);
524                     TSOMaterial[] mtllist = new TSOMaterial[materialmap.Count];
525
526                     foreach (var i in materialmap.Values)
527                         mtllist[i.Second] = i.First;
528
529                     foreach (TSOMesh mesh in meshes)
530                     {
531                         foreach (TSOSubMesh sub in mesh.sub_meshes)
532                         {
533                             TSOMaterial spec = mesh.file.materials[sub.spec];
534                             sub.spec = materialmap[spec.Name].Second;
535                         }
536                     }
537
538                     foreach (TSOTex tex in texlist)
539                         TSOFile.ExchangeChannel(tex.data, tex.depth);
540
541                     BinaryWriter bw = new BinaryWriter(fs);
542                     TSOWriter.WriteHeader(bw);
543                     TSOWriter.Write(bw, last.nodes);
544                     TSOWriter.Write(bw, texlist.ToArray());
545                     TSOWriter.Write(bw, last.effects);
546                     TSOWriter.Write(bw, mtllist);
547                     TSOWriter.Write(bw, meshes.ToArray());
548                 }
549             }
550             catch (Exception exception)
551             {
552                 Util.ProcessError(exception);
553             }
554             finally
555             {
556                 tabPage2.BackColor = c;
557             }
558         }
559
560         private void btnMergeAdd_Click(object sender, EventArgs e)
561         {
562             try
563             {
564                 OpenFileDialog dlg = new OpenFileDialog();
565                 dlg.Filter = "TSO File(*.tso)|*.tso";
566                 dlg.Multiselect = true;
567
568                 if (dlg.ShowDialog() == DialogResult.OK)
569                     AddMergeTso(dlg.FileNames);
570             }
571             catch (Exception exception)
572             {
573                 Util.ProcessError(exception);
574             }
575         }
576
577         private void btnMergeDel_Click(object sender, EventArgs e)
578         {
579             if (tvMerge.SelectedNode != null && tvMerge.SelectedNode.Level == 0)
580                 tvMerge.SelectedNode.Remove();
581         }
582
583         private void btnMergeReset_Click(object sender, EventArgs e)
584         {
585             tvMerge.Nodes.Clear();
586         }
587
588         private void btnRefMergeTso_Click(object sender, EventArgs e)
589         {
590             try
591             {
592                 SaveFileDialog dlg = new SaveFileDialog();
593                 dlg.Filter = "TSO File (*.tso)|*.tso";
594                 dlg.FileName = tbMergeTso.Text;
595
596                 if (dlg.ShowDialog() == DialogResult.OK)
597                     tbMergeTso.Text = dlg.FileName;
598             }
599             catch (Exception exception)
600             {
601                 Util.ProcessError(exception);
602             }
603         }
604
605         public static bool bTvMerge_AfterCheck = false;
606
607         private void tvMerge_AfterCheck(object sender, TreeViewEventArgs e)
608         {
609             if (bTvMerge_AfterCheck)
610                 return;
611
612             bTvMerge_AfterCheck = true;
613
614             try
615             {
616                 if (e.Node.Level == 0)
617                 {
618                     foreach (TreeNode node in e.Node.Nodes)
619                         node.Checked = e.Node.Checked;
620                 }
621                 else
622                 {
623                     bool check = false;
624
625                     foreach (TreeNode node in e.Node.Parent.Nodes)
626                         if (node.Checked) check = true;
627
628                     e.Node.Parent.Checked = check;
629                 }
630             }
631             finally
632             {
633                 bTvMerge_AfterCheck = false;
634             }
635         }
636         #endregion
637     }
638
639     public class Util
640     {
641         public static void ProcessError(Exception exception)
642         {
643             MessageBox.Show(exception.ToString());
644         }
645     }
646 }