private async void ImportButton_Click(object sender, RoutedEventArgs e) { var path = PathBox.Text; if (String.IsNullOrWhiteSpace(path)) { return; } var od = new OpenFileDialog(); var result = od.ShowDialog(); if (result != System.Windows.Forms.DialogResult.OK) { return; } byte[] data = null; var _dat = new Dat(XivCache.GameInfo.GameDirectory); var _index = new Index(XivCache.GameInfo.GameDirectory); if (DecompressedType2.IsChecked == true) { var temp = File.ReadAllBytes(od.FileName); data = await _dat.CreateType2Data(temp); } else { data = File.ReadAllBytes(od.FileName); } var type = BitConverter.ToInt32(data, 4); if (type < 2 || type > 4) { FlexibleMessageBox.Show("Invalid Data Type.\nGeneric binary files should be imported as decompressed type 2 Data.", "Data Type Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } try { var dummyItem = new XivGenericItemModel(); dummyItem.Name = Path.GetFileName(path); dummyItem.SecondaryCategory = "Raw File Imports"; await _dat.WriteModFile(data, path, XivStrings.TexTools, dummyItem); } catch (Exception Ex) { FlexibleMessageBox.Show("Unable to import file.\n\nError: " + Ex.Message, "Import Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } FlexibleMessageBox.Show("File Imported Successfully.", "Import Success", MessageBoxButtons.OK, MessageBoxIcon.Information); this.Close(); }
private async void AddMetadataButton_Click(object sender, RoutedEventArgs e) { var path = MetadataPathBox.Text; var selectedFile = new FileEntry() { Path = path, Name = MakeFriendlyFileName(path) }; var addChildren = MetadataIncludeChildFilesBox.IsChecked == true ? true : false; var _dat = new Dat(_gameDirectory); var meta = await ItemMetadata.GetMetadata(path); var data = await _dat.CreateType2Data(await ItemMetadata.Serialize(meta)); if (addChildren) { AddWithChildren(selectedFile.Path, SelectedItem, data); } else { AddFile(selectedFile, SelectedItem, data); } }
/// <summary> /// Creates texture data ready to be imported into the DATs from an external file. /// If format is not specified, either the incoming file's DDS format is used (DDS files), /// or the existing internal file's DDS format is used. /// </summary> /// <param name="internalPath"></param> /// <param name="externalPath"></param> /// <param name="texFormat"></param> /// <returns></returns> public async Task <byte[]> MakeTexData(string internalPath, string externalPath, XivTexFormat texFormat = XivTexFormat.INVALID) { // Ensure file exists. if (!File.Exists(externalPath)) { throw new IOException($"Could not find file: {externalPath}"); } var root = await XivCache.GetFirstRoot(internalPath); bool isDds = Path.GetExtension(externalPath).ToLower() == ".dds"; var ddsContainer = new DDSContainer(); try { // If no format was specified... if (texFormat == XivTexFormat.INVALID) { if (isDds) { // If we're importing a DDS file, get the format from the incoming DDS file using (var fs = new FileStream(externalPath, FileMode.Open)) { using (var sr = new BinaryReader(fs)) { texFormat = GetDDSTexFormat(sr); } } } else { // Otherwise use the current internal format. var xivt = await _dat.GetType4Data(internalPath, false); texFormat = xivt.TextureFormat; } } // Check if the texture being imported has been imported before CompressionFormat compressionFormat = CompressionFormat.BGRA; switch (texFormat) { case XivTexFormat.DXT1: compressionFormat = CompressionFormat.BC1a; break; case XivTexFormat.DXT5: compressionFormat = CompressionFormat.BC3; break; case XivTexFormat.A8R8G8B8: compressionFormat = CompressionFormat.BGRA; break; default: if (!isDds) { throw new Exception($"Format {texFormat} is not currently supported for BMP import\n\nPlease use the DDS import option instead."); } break; } if (!isDds) { using (var surface = Surface.LoadFromFile(externalPath)) { if (surface == null) { throw new FormatException($"Unsupported texture format"); } surface.FlipVertically(); var maxMipCount = 1; if (root != null) { // For things that have real roots (things that have actual models/aren't UI textures), we always want mipMaps, even if the existing texture only has one. // (Ex. The Default Mat-Add textures) maxMipCount = -1; } using (var compressor = new Compressor()) { // UI/Paintings only have a single mipmap and will crash if more are generated, for everything else generate max levels compressor.Input.SetMipmapGeneration(true, maxMipCount); compressor.Input.SetData(surface); compressor.Compression.Format = compressionFormat; compressor.Compression.SetBGRAPixelFormat(); compressor.Process(out ddsContainer); } } } // If we're not a DDS, write the DDS to file temporarily. var ddsFilePath = externalPath; if (!isDds) { var tempFile = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString() + ".dds"); ddsContainer.Write(tempFile, DDSFlags.None); ddsFilePath = tempFile; } using (var br = new BinaryReader(File.OpenRead(ddsFilePath))) { br.BaseStream.Seek(12, SeekOrigin.Begin); var newHeight = br.ReadInt32(); var newWidth = br.ReadInt32(); br.ReadBytes(8); var newMipCount = br.ReadInt32(); if (newHeight % 2 != 0 || newWidth % 2 != 0) { throw new Exception("Resolution must be a multiple of 2"); } br.BaseStream.Seek(80, SeekOrigin.Begin); var textureFlags = br.ReadInt32(); var texType = br.ReadInt32(); var uncompressedLength = (int)new FileInfo(ddsFilePath).Length - 128; var newTex = new List <byte>(); if (!internalPath.Contains(".atex")) { var DDSInfo = await DDS.ReadDDS(br, texFormat, newWidth, newHeight, newMipCount); newTex.AddRange(_dat.MakeType4DatHeader(texFormat, DDSInfo.mipPartOffsets, DDSInfo.mipPartCounts, (int)uncompressedLength, newMipCount, newWidth, newHeight)); newTex.AddRange(MakeTextureInfoHeader(texFormat, newWidth, newHeight, newMipCount)); newTex.AddRange(DDSInfo.compressedDDS); return(newTex.ToArray()); } else { br.BaseStream.Seek(128, SeekOrigin.Begin); newTex.AddRange(MakeTextureInfoHeader(texFormat, newWidth, newHeight, newMipCount)); newTex.AddRange(br.ReadBytes((int)uncompressedLength)); var data = await _dat.CreateType2Data(newTex.ToArray()); return(data); } } } finally { ddsContainer.Dispose(); } }
/// <summary> /// The event handler for the add custom texture button clicked /// </summary> private async void AddCustomTextureButton_Click(object sender, RoutedEventArgs e) { var selectedItem = TextureMapComboBox.SelectedItem as ModComboBox; var mod = selectedItem.SelectedMod; byte[] modData; var includedMod = new IncludedMods { Name = $"{Path.GetFileNameWithoutExtension(mod.fullPath)} ({((Category)ModListTreeView.SelectedItem).Name})", FullPath = mod.fullPath }; var includedModsList = IncludedModsList.Items.Cast <IncludedMods>().ToList(); var tex = new Tex(_gameDirectory); var ddsDirectory = new DirectoryInfo(CustomTextureTextBox.Text); if (selectedItem.TexTypePath.Type == XivTexType.ColorSet) { var mtrl = new Mtrl(_gameDirectory, XivDataFiles.GetXivDataFile(mod.datFile), GetLanguage()); var xivMtrl = await mtrl.GetMtrlData(mod.data.modOffset, mod.fullPath, int.Parse(Settings.Default.DX_Version)); modData = tex.DDStoMtrlData(xivMtrl, ddsDirectory, ((Category)ModListTreeView.SelectedItem).Item, GetLanguage()); var dat = new Dat(_gameDirectory); modData = await dat.CreateType2Data(modData); } else { try { var texData = await tex.GetTexData(selectedItem.TexTypePath); modData = await tex.DDStoTexData(texData, ((Category)ModListTreeView.SelectedItem).Item, ddsDirectory); } catch (Exception ex) { FlexibleMessageBox.Show(ex.Message); return; } } if (includedModsList.Any(item => item.Name.Equals(includedMod.Name))) { if (FlexibleMessageBox.Show( string.Format(UIMessages.ExistingOption, includedMod.Name), UIMessages.OverwriteTitle, MessageBoxButtons.YesNo, MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.Yes) { _selectedModOption.Mods[mod.fullPath].ModDataBytes = modData; } } else { IncludedModsList.Items.Add(includedMod); _selectedModOption.Mods.Add(mod.fullPath, new ModData { Name = mod.name, Category = mod.category, FullPath = mod.fullPath, ModDataBytes = modData, }); } }