Пример #1
0
            public void Write(Stream output, FindLogic.Combo.ComboInfo info, FindLogic.Combo.MaterialInfo materialInfo)
            {
                using (BinaryWriter writer = new BinaryWriter(output)) {
                    FindLogic.Combo.MaterialDataInfo materialDataInfo = info.MaterialDatas[materialInfo.MaterialData];
                    writer.Write(VersionMajor);
                    writer.Write(VersionMinor);
                    writer.Write(materialDataInfo.Textures.LongCount());
                    writer.Write((uint)OWMatType.Material);
                    writer.Write(GUID.Index(materialInfo.Shader));
                    writer.Write(materialInfo.IDs.Count);
                    foreach (ulong id in materialInfo.IDs)
                    {
                        writer.Write(id);
                    }

                    foreach (KeyValuePair <ulong, ImageDefinition.ImageType> texture in materialDataInfo.Textures)
                    {
                        if (info.Textures.ContainsKey(texture.Key))
                        {
                            FindLogic.Combo.TextureInfoNew textureInfo = info.Textures[texture.Key];
                            writer.Write($"..\\Textures\\{textureInfo.GetNameIndex()}.dds");
                        }
                        else
                        {
                            writer.Write("");
                        }

                        writer.Write((uint)texture.Value);
                    }
                }
            }
Пример #2
0
            public void Write(Stream stream)
            {
                using (BinaryWriter writer = new BinaryWriter(stream)) {
                    FindLogic.Combo.MaterialDataInfo materialDataInfo = Info.MaterialDatas[MaterialInfo.MaterialData];
                    writer.Write(VersionMajor);
                    writer.Write(VersionMinor);
                    if (materialDataInfo.Textures != null)
                    {
                        writer.Write(materialDataInfo.Textures.LongCount());
                    }
                    else
                    {
                        writer.Write(0L);
                    }
                    writer.Write((uint)OWMatType.Material);
                    writer.Write(teResourceGUID.Index(MaterialInfo.ShaderSource));
                    writer.Write(MaterialInfo.MaterialIDs.Count);
                    foreach (ulong id in MaterialInfo.MaterialIDs)
                    {
                        writer.Write(id);
                    }

                    if (materialDataInfo.Textures != null)
                    {
                        foreach (KeyValuePair <ulong, uint> texture in materialDataInfo.Textures)
                        {
                            FindLogic.Combo.TextureInfoNew textureInfo = Info.Textures[texture.Key];
                            if (stream is FileStream fs)
                            {
                                writer.Write(Combo.GetScratchRelative(textureInfo.GUID, Path.GetDirectoryName(fs.Name), $@"..\Textures\{textureInfo.GetNameIndex()}.dds"));
                            }
                            else
                            {
                                writer.Write($@"..\Textures\{textureInfo.GetNameIndex()}.dds");
                            }
                            writer.Write(texture.Value);
                        }
                    }
                }
            }
Пример #3
0
        public static void SaveTexture(ICLIFlags flags, string path, FindLogic.Combo.ComboInfo info, ulong textureGUID)
        {
            bool   convertTextures = true;
            string convertType     = "dds";
            bool   lossless        = false;

            if (flags is ExtractFlags extractFlags)
            {
                convertTextures = extractFlags.ConvertTextures && !extractFlags.Raw;
                convertType     = extractFlags.ConvertTexturesType.ToLowerInvariant();
                lossless        = extractFlags.ConvertTexturesLossless;
                if (extractFlags.SkipTextures)
                {
                    return;
                }
            }
            path += Path.DirectorySeparatorChar;

            FindLogic.Combo.TextureInfoNew textureInfo = info.Textures[textureGUID];
            string filePath = Path.Combine(path, $"{textureInfo.GetNameIndex()}");

            if (Program.Flags.Deduplicate)
            {
                if (ScratchDBInstance.HasRecord(textureGUID))
                {
                    return;
                }
                ScratchDBInstance[textureGUID] = new ScratchDB.ScratchPath($"{filePath}.{convertType}");
            }

            CreateDirectoryFromFile(path);
            if (!convertTextures)
            {
                using (Stream textureStream = OpenFile(textureInfo.GUID)) {
                    teTexture texture = new teTexture(textureStream, true);
                    textureStream.Position = 0;
                    WriteFile(textureStream, $"{filePath}.004");

                    if (!texture.PayloadRequired)
                    {
                        return;
                    }
                    using (Stream texturePayloadStream = OpenFile(texture.GetPayloadGUID(textureGUID)))
                        WriteFile(texturePayloadStream, $"{filePath}.04D");
                }
            }
            else
            {
                using (Stream textureStream = OpenFile(textureGUID)) {
                    if (textureStream == null)
                    {
                        return;
                    }
                    teTexture texture = new teTexture(textureStream);

                    if (texture.PayloadRequired)
                    {
                        texture.LoadPayload(OpenFile(texture.GetPayloadGUID(textureGUID)));
                    }

                    using (Stream convertedStream = texture.SaveToDDS()) {
                        convertedStream.Position = 0;
                        if (convertType == "dds" || convertedStream.Length == 0)
                        {
                            WriteFile(convertedStream, $"{filePath}.dds");
                            return;
                        }

                        uint fourCC      = texture.Header.GetFormat().ToPixelFormat().FourCC;
                        bool isBcffValid = TextureConfig.DXGI_BC4.Contains((int)texture.Header.Format) ||
                                           TextureConfig.DXGI_BC5.Contains((int)texture.Header.Format) ||
                                           fourCC == TextureConfig.FOURCC_ATI1 || fourCC == TextureConfig.FOURCC_ATI2;


                        ImageFormat imageFormat = null;
                        if (convertType == "tif")
                        {
                            imageFormat = ImageFormat.Tiff;
                        }
                        // if (convertType == "tga") imageFormat = Im.... oh
                        // so there is no TGA image format.
                        // guess the TGA users are stuck with the DirectXTex stuff for now.

                        if (isBcffValid && imageFormat != null)
                        {
                            BlockDecompressor decompressor = new BlockDecompressor(convertedStream);
                            decompressor.CreateImage();
                            decompressor.Image.Save($"{filePath}.{convertType}", imageFormat);
                            return;
                        }

                        string losslessFlag = lossless ? "-wiclossless" : string.Empty;

                        Process pProcess = new Process {
                            StartInfo =
                            {
                                FileName               = "Third Party\\texconv.exe",
                                UseShellExecute        = false,
                                RedirectStandardOutput = true,
                                RedirectStandardInput  = true,
                                RedirectStandardError  = true,
                                CreateNoWindow         = true,
                                Arguments              =
                                    $"-- \"{Path.GetFileName(filePath)}.dds\" -y -wicmulti {losslessFlag} -nologo -m 1 -ft {convertType} -f R8G8B8A8_UNORM -o \"{path}"
                            },
                            EnableRaisingEvents = true
                        };

                        // erm, so if you add an end quote to this then it breaks.
                        // but start one on it's own is fine (we need something for "Winged Victory")
                        pProcess.Start();
                        convertedStream.Position = 0;
                        convertedStream.CopyTo(pProcess.StandardInput.BaseStream);
                        pProcess.StandardInput.BaseStream.Close();

                        // pProcess.WaitForExit(); // not using this is kinda dangerous but I don't care
                        // when texconv writes with to the console -nologo is has done/failed conversion
                        string line = pProcess.StandardOutput.ReadLine();
                        if (line?.Contains("FAILED") == true)
                        {
                            convertedStream.Position = 0;
                            WriteFile(convertedStream, $"{filePath}.dds");
                        }
                    }
                }
            }
        }
Пример #4
0
        public static void SaveTexture(ICLIFlags flags, string path, FindLogic.Combo.ComboInfo info, ulong texture)
        {
            bool   convertTextures = true;
            string convertType     = "dds";

            if (flags is ExtractFlags extractFlags)
            {
                convertTextures = extractFlags.ConvertTextures && !extractFlags.Raw;
                convertType     = extractFlags.ConvertTexturesType.ToLowerInvariant();
                if (extractFlags.SkipTextures)
                {
                    return;
                }
            }
            path += Path.DirectorySeparatorChar;

            FindLogic.Combo.TextureInfoNew textureInfo = info.Textures[texture];
            string filePath = Path.Combine(path, $"{textureInfo.GetNameIndex()}");

            if (!convertTextures)
            {
                CreateDirectoryFromFile(path);
                using (Stream textureStream = OpenFile(textureInfo.GUID))
                    WriteFile(textureStream, $"{filePath}.004");

                if (!textureInfo.UseData)
                {
                    return;
                }
                using (Stream textureStream = OpenFile(textureInfo.DataGUID))
                    WriteFile(textureStream, $"{filePath}.04D");
            }
            else
            {
                Stream headerStream = OpenFile(textureInfo.GUID);
                Stream dataStream   = null;
                if (headerStream == null)
                {
                    return;
                }
                if (textureInfo.UseData)
                {
                    dataStream = OpenFile(textureInfo.DataGUID);
                    if (dataStream == null)
                    {
                        return;
                    }
                }

                if (info.SaveRuntimeData.Threads)
                {
                    info.SaveRuntimeData.Tasks.Add(Task.Run(() => {
                        ConvertTexture(convertType, filePath, path, headerStream, dataStream);
                    }));
                }
                else
                {
                    ConvertTexture(convertType, filePath, path, headerStream, dataStream);
                }
            }
        }
Пример #5
0
        public static void SaveTexture(ICLIFlags flags, string path, FindLogic.Combo.ComboInfo info, ulong textureGUID)
        {
            bool   convertTextures         = true;
            string convertType             = "tif";
            string multiSurfaceConvertType = "tif";
            bool   createMultiSurfaceSheet = false;
            bool   lossless = false;
            int    maxMips  = 1;

            if (flags is ExtractFlags extractFlags)
            {
                if (extractFlags.SkipTextures)
                {
                    return;
                }
                createMultiSurfaceSheet = extractFlags.SheetMultiSurface;
                convertTextures         = !extractFlags.RawTextures && !extractFlags.Raw;
                convertType             = extractFlags.ConvertTexturesType.ToLowerInvariant();
                lossless = extractFlags.ConvertTexturesLossless;

                multiSurfaceConvertType = convertType;
                if (extractFlags.ForceDDSMultiSurface)
                {
                    multiSurfaceConvertType = "dds";
                }

                if (convertType == "dds" && extractFlags.SaveMips)
                {
                    maxMips = 0xF;
                }
            }
            path += Path.DirectorySeparatorChar;

            FindLogic.Combo.TextureInfoNew textureInfo = info.Textures[textureGUID];
            string filePath = Path.Combine(path, $"{textureInfo.GetNameIndex()}");

            if (teResourceGUID.Type(textureGUID) != 0x4)
            {
                filePath += $".{teResourceGUID.Type(textureGUID):X3}";
            }

            if (Program.Flags.Deduplicate)
            {
                if (ScratchDBInstance.HasRecord(textureGUID))
                {
                    return;
                }
                ScratchDBInstance[textureGUID] = new ScratchDB.ScratchPath($"{filePath}.{convertType}");
            }

            CreateDirectoryFromFile(path);
            if (!convertTextures)
            {
                using (Stream textureStream = OpenFile(textureGUID)) {
                    teTexture texture = new teTexture(textureStream, true);
                    textureStream.Position = 0;
                    WriteFile(textureStream, $"{filePath}.004");

                    if (!texture.PayloadRequired)
                    {
                        return;
                    }
                    for (int i = 0; i < texture.Payloads.Length; ++i)
                    {
                        using (Stream texturePayloadStream = OpenFile(texture.GetPayloadGUID(textureGUID, i)))
                            WriteFile(texturePayloadStream, $"{filePath}_{i}.04D");
                    }
                }
            }
            else
            {
                using (Stream textureStream = OpenFile(textureGUID)) {
                    if (textureStream == null)
                    {
                        return;
                    }
                    teTexture texture = new teTexture(textureStream);

                    //if (texture.Header.Flags.HasFlag(teTexture.Flags.CUBEMAP)) return;
                    // for diffing when they add/regen loads of cubemaps

                    if (texture.PayloadRequired)
                    {
                        for (int i = 0; i < texture.Payloads.Length; ++i)
                        {
                            texture.LoadPayload(OpenFile(texture.GetPayloadGUID(textureGUID, i)), i);
                            if (maxMips == 1)
                            {
                                break;
                            }
                        }
                    }

                    uint?width    = null;
                    uint?height   = null;
                    uint?surfaces = null;
                    if (texture.Header.IsCubemap || texture.Header.IsArray || texture.HasMultipleSurfaces)
                    {
                        if (createMultiSurfaceSheet)
                        {
                            TankLib.Helpers.Logger.Debug("Combo", $"Saving {Path.GetFileName(filePath)} as a sheet because it has more than one surface");
                            height               = (uint)(texture.Header.Height * texture.Header.Surfaces);
                            surfaces             = 1;
                            texture.Header.Flags = 0;
                        }
                        else
                        {
                            TankLib.Helpers.Logger.Debug("Combo", $"Saving {Path.GetFileName(filePath)} as {multiSurfaceConvertType} because it has more than one surface");
                            convertType = multiSurfaceConvertType;
                        }
                    }

                    using (Stream convertedStream = texture.SaveToDDS(maxMips == 1 ? 1 : texture.Header.MipCount, width, height, surfaces)) {
                        convertedStream.Position = 0;
                        if (convertType == "dds" || convertedStream.Length == 0)
                        {
                            WriteFile(convertedStream, $"{filePath}.dds");
                            return;
                        }

                        bool isBcffValid = teTexture.DXGI_BC4.Contains(texture.Header.Format) ||
                                           teTexture.DXGI_BC5.Contains(texture.Header.Format) ||
                                           teTexture.ATI2.Contains(texture.Header.GetTextureType());

                        ImageFormat imageFormat = null;
                        if (convertType == "tif")
                        {
                            imageFormat = ImageFormat.Tiff;
                        }
                        if (convertType == "png")
                        {
                            imageFormat = ImageFormat.Png;
                        }
                        if (convertType == "jpg")
                        {
                            imageFormat = ImageFormat.Jpeg;
                        }
                        // if (convertType == "tga") imageFormat = Im.... oh
                        // so there is no TGA image format.
                        // guess the TGA users are stuck with the DirectXTex stuff for now.

                        if (isBcffValid && imageFormat != null && !(texture.Header.IsCubemap || texture.Header.IsArray || texture.HasMultipleSurfaces))
                        {
                            BlockDecompressor decompressor = new BlockDecompressor(convertedStream);
                            decompressor.CreateImage();
                            decompressor.Image.Save($"{filePath}.{convertType}", imageFormat);
                            return;
                        }

                        string losslessFlag = lossless ? "-wiclossless" : string.Empty;

                        Process pProcess = new Process {
                            StartInfo =
                            {
                                FileName               = "Third Party\\texconv.exe",
                                UseShellExecute        = false,
                                RedirectStandardOutput = true,
                                RedirectStandardInput  = true,
                                RedirectStandardError  = true,
                                CreateNoWindow         = true,
                                Arguments              =
                                    $"-- \"{Path.GetFileName(filePath)}.dds\" -y -wicmulti {losslessFlag} -nologo -m 1 -ft {convertType} -f R8G8B8A8_UNORM -o \"{(path.EndsWith(@"/") || path.EndsWith("\\") ? path.Substring(0, path.Length - 1) : path)}"
                            },
                            EnableRaisingEvents = true
                        };

                        pProcess.Start();
                        convertedStream.Position = 0;
                        convertedStream.CopyTo(pProcess.StandardInput.BaseStream);
                        pProcess.StandardInput.BaseStream.Flush();
                        pProcess.StandardInput.BaseStream.Close();
                        pProcess.WaitForExit();
                        // when texconv writes with to the console -nologo is has done/failed conversion
                        string line = pProcess.StandardOutput.ReadToEnd();
                        if (line.Contains("FAILED"))
                        {
                            convertedStream.Position = 0;
                            TankLib.Helpers.Logger.Debug("Combo", $"Saving {Path.GetFileName(filePath)} as dds because texconv failed.");
                            WriteFile(convertedStream, $"{filePath}.dds");
                        }
                    }
                }
            }
        }