public override void writer(MFileObject file, string optionsString, FileAccessMode mode)
        {
            if (mode == FileAccessMode.kExportActiveAccessMode)
            {
                string sknPath = file.expandedFullName;
                string sklPath = Path.ChangeExtension(sknPath, ".skl");

                SKLFile skl = new SKLFile(true);
                SKNFile skn = new SKNFile(skl);

                skl.Write(sklPath);
                skn.Write(sknPath);
            }
            else
            {
                MGlobal.displayError("SKNExporter - Wrong File Access Mode: " + mode);
            }
        }
        /// <summary>
        /// 导出skn为obj
        /// </summary>
        /// <param name="selectedPath"></param>
        /// <param name="entries"></param>
        private void ExtractWADEntriesObj(string selectedPath, List <WADEntry> entries)
        {
            this.progressBarWadExtraction.Maximum = entries.Count;
            this.IsEnabled = false;

            BackgroundWorker wadExtractor = new BackgroundWorker
            {
                WorkerReportsProgress = true
            };

            wadExtractor.ProgressChanged += (sender, args) =>
            {
                this.progressBarWadExtraction.Value = args.ProgressPercentage;
            };

            wadExtractor.DoWork += (sender, e) =>
            {
                Dictionary <string, byte[]> fileEntries = new Dictionary <string, byte[]>();
                double progress = 0;
                bool   createPackedMappingFile  = false;
                string packedMappingFileContent = "";

                foreach (WADEntry entry in entries)
                {
                    byte[] entryData = entry.GetContent(true);
                    string entryName;
                    if (StringDictionary.ContainsKey(entry.XXHash))
                    {
                        entryName = StringDictionary[entry.XXHash];

                        if (Regex.IsMatch(entryName, @"^DATA/.*_Skins_Skin.*\.bin$"))
                        {
                            createPackedMappingFile = true;
                            entryName = entry.XXHash.ToString("X16") + ".bin";
                            packedMappingFileContent += string.Format("{0} = {1}\n", entryName, StringDictionary[entry.XXHash]);
                        }
                        else
                        {
                            Directory.CreateDirectory(Path.Combine(selectedPath, Path.GetDirectoryName(entryName) ?? ""));
                        }
                    }
                    else
                    {
                        entryName = entry.XXHash.ToString("X16") + "." + Utilities.GetEntryExtension(Utilities.GetLeagueFileExtensionType(entryData));
                    }

                    fileEntries.Add(entryName, entryData);
                    progress += 0.5;
                    wadExtractor.ReportProgress((int)progress);
                }

                if ((bool)this.Config["ParallelExtraction"])
                {
                    Parallel.ForEach(fileEntries, entry =>
                    {
                        //File.WriteAllBytes(Path.Combine(selectedPath, entry.Key), entry.Value);
                        SKNFile sknFile = new SKNFile(new MemoryStream(entry.Value));
                        sknFile.Write(Path.Combine(selectedPath, entry.Key));
                        progress += 0.5;
                        wadExtractor.ReportProgress((int)progress);
                    });
                }
                else
                {
                    foreach (KeyValuePair <string, byte[]> entry in fileEntries)
                    {
                        File.WriteAllBytes(Path.Combine(selectedPath, entry.Key), entry.Value);

                        progress += 0.5;
                        wadExtractor.ReportProgress((int)progress);
                    }
                }

                if (createPackedMappingFile)
                {
                    File.WriteAllText(Path.Combine(selectedPath, "OBSIDIAN_PACKED_MAPPING.txt"), packedMappingFileContent);
                }
            };

            wadExtractor.RunWorkerCompleted += (sender, args) =>
            {
                if (args.Error != null)
                {
                    MessageBox.Show(string.Format("An error occured:\n{0}", args.Error), "", MessageBoxButton.OK, MessageBoxImage.Error);
                    Logger.Error(string.Format("WAD extraction failed:\n{0}", args.Error));
                }
                else
                {
                    MessageBox.Show("Extraction Successful!", "", MessageBoxButton.OK, MessageBoxImage.Information);
                    Logger.Info("WAD Extraction Successful!");
                }

                this.progressBarWadExtraction.Maximum = 100;
                this.progressBarWadExtraction.Value   = 100;
                this.IsEnabled = true;
            };

            wadExtractor.RunWorkerAsync();
        }