OSDN Git Service

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