public void Write(Stream stream) { using (BinaryWriter writer = new BinaryWriter(stream)) { FindLogic.Combo.MaterialDataAsset materialDataInfo = Info.m_materialData[MaterialInfo.m_materialDataGUID]; writer.Write(VersionMajor); writer.Write(VersionMinor); if (materialDataInfo.m_textureMap != null) { writer.Write(materialDataInfo.m_textureMap.LongCount()); } else { writer.Write(0L); } writer.Write((uint)OWMatType.Material); writer.Write(teResourceGUID.Index(MaterialInfo.m_shaderSourceGUID)); writer.Write(MaterialInfo.m_materialIDs.Count); foreach (ulong id in MaterialInfo.m_materialIDs) { writer.Write(id); } if (materialDataInfo.m_textureMap != null) { foreach (KeyValuePair <ulong, uint> texture in materialDataInfo.m_textureMap) { FindLogic.Combo.TextureAsset textureInfo = Info.m_textures[texture.Key]; if (stream is FileStream fs) { writer.Write(Combo.GetScratchRelative(textureInfo.m_GUID, Path.GetDirectoryName(fs.Name), $@"..\Textures\{textureInfo.GetNameIndex()}.dds")); } else { writer.Write($@"..\Textures\{textureInfo.GetNameIndex()}.dds"); } writer.Write(texture.Value); } } } }
private static async Task SaveTextureTask(ICLIFlags flags, string path, SaveContext info, ulong textureGUID, string name = null) { 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; } } if (!path.EndsWith(Path.DirectorySeparatorChar.ToString())) { path += Path.DirectorySeparatorChar; } FindLogic.Combo.TextureAsset textureInfo = info.m_info.m_textures[textureGUID]; string filePath = Path.Combine(path, name ?? $"{textureInfo.GetNameIndex()}"); if (teResourceGUID.Type(textureGUID) != 0x4) { filePath += $".{teResourceGUID.Type(textureGUID):X3}"; } if (Program.Flags != null && Program.Flags.Deduplicate) { if (ScratchDBInstance.HasRecord(textureGUID)) { return; } ScratchDBInstance[textureGUID] = new ScratchDB.ScratchPath($"{filePath}.{convertType}", true); } CreateDirectoryFromFile(path); await s_texurePrepareSemaphore.WaitAsync(); try { if (!convertTextures) { teTexture texture; using (Stream textureStream = OpenFile(textureGUID)) { 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 { teTexture texture; using (Stream textureStream = OpenFile(textureGUID)) { if (textureStream == null) { return; } 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) { using (var payloadStream = OpenFile(texture.GetPayloadGUID(textureGUID, i))) texture.LoadPayload(payloadStream, 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) { 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 if (convertType != "tif" && convertType != "dds") { Logger.Debug("Combo", $"Saving {Path.GetFileName(filePath)} as {multiSurfaceConvertType} because it has more than one surface"); convertType = multiSurfaceConvertType; } } WICCodecs?imageFormat = null; switch (convertType) { case "tif": imageFormat = WICCodecs.TIFF; break; case "png": imageFormat = WICCodecs.PNG; break; case "jpg": imageFormat = WICCodecs.JPEG; break; } // if (convertType == "tga") imageFormat = Im.... oh // so there is no TGA image format. // sucks to be them if (convertType == "dds") { using (Stream convertedStream = texture.SaveToDDS(maxMips == 1 ? 1 : texture.Header.MipCount, width, height, surfaces)) { WriteFile(convertedStream, $"{filePath}.dds"); } return; } Process pProcess; using (Stream convertedStream = texture.SaveToDDS(maxMips == 1 ? 1 : texture.Header.MipCount, width, height, surfaces)) { var data = DDSConverter.ConvertDDS(convertedStream, DXGI_FORMAT.R8G8B8A8_UNORM, imageFormat.Value, 0); if (data != null) { WriteFile(data, $"{filePath}.{convertType}"); } else { convertedStream.Position = 0; WriteFile(convertedStream, $"{filePath}.dds"); Logger.Error("Combo", $"Unable to save {Path.GetFileName(filePath)} as {convertType} because DirectXTex failed."); } } } } finally { s_texurePrepareSemaphore.Release(); } }