private static int ExportTaskInner(string path, EUncookExtension uncookext) { #region checks if (string.IsNullOrEmpty(path)) { logger.LogString("Please fill in an input path.", Logtype.Error); return(0); } var inputFileInfo = new FileInfo(path); if (!inputFileInfo.Exists) { logger.LogString("Input file does not exist.", Logtype.Error); return(0); } #endregion if (ModTools.Export(new FileInfo(path), uncookext) == 1) { logger.LogString($"Successfully exported {path}.", Logtype.Success); } else { logger.LogString($"Failed to export {path}.", Logtype.Error); } return(1); }
private static int ExportTaskInner(string path, EUncookExtension uncookext) { #region checks if (string.IsNullOrEmpty(path)) { logger.LogString("Please fill in an input path.", Logtype.Error); return(0); } var inputFileInfo = new FileInfo(path); if (!inputFileInfo.Exists) { logger.LogString("Input file does not exist.", Logtype.Error); return(0); } #endregion Stopwatch watch = new(); watch.Restart(); if (ModTools.Export(new FileInfo(path), uncookext)) { watch.Stop(); logger.LogString($"Successfully exported {path} in {watch.ElapsedMilliseconds.ToString()}ms.", Logtype.Success); } else { watch.Stop(); logger.LogString($"Failed to export {path}.", Logtype.Error); } return(1); }
public static int Convert(string outDir, string filepath, EUncookExtension convertFt, EFormat convertF = EFormat.R8G8B8A8_UNORM, bool overwrite = true ) { var fi = new FileInfo(textconvpath); if (!fi.Exists) { } var proc = new ProcessStartInfo(textconvpath) { WorkingDirectory = Path.GetDirectoryName(textconvpath), Arguments = $" -o {outDir} -y -f {convertF} -ft {convertFt} {filepath}", UseShellExecute = false, RedirectStandardOutput = true, CreateNoWindow = true, }; using (var p = Process.Start(proc)) { p.WaitForExit(); } return(1); }
/// <summary> /// Uncooks a single file by hash. This will both extract and uncook the redengine file /// </summary> /// <param name="ar"></param> /// <param name="hash"></param> /// <param name="outDir"></param> /// <param name="uncookext"></param> /// <param name="flip"></param> /// <returns></returns> public static bool UncookSingle(this Archive.Archive ar, ulong hash, DirectoryInfo outDir, EUncookExtension uncookext = EUncookExtension.dds, bool flip = false) { // checks if (!ar.Files.ContainsKey(hash)) { return(false); } // extract the main file with uncompressed buffers #region unbundle main file using var ms = new MemoryStream(); ar.CopyFileToStream(ms, hash, false); var name = ar.Files[hash].FileName; var outfile = new FileInfo(Path.Combine(outDir.FullName, $"{name}")); if (outfile.Directory == null) { return(false); } Directory.CreateDirectory(outfile.Directory.FullName); using var fs = new FileStream(outfile.FullName, FileMode.Create, FileAccess.Write); ms.Seek(0, SeekOrigin.Begin); ms.CopyTo(fs); #endregion var ext = Path.GetExtension(name)[1..];
public static string Convert(string outDir, string filepath, EUncookExtension filetype, EFormat format = EFormat.R8G8B8A8_UNORM, int mipmaps = 0 ) { var proc = new ProcessStartInfo(textconvpath) { WorkingDirectory = Path.GetDirectoryName(textconvpath), Arguments = $" -o \"{outDir}\" -y -f {format} -m {mipmaps} -l -ft {filetype} \"{filepath}\"", UseShellExecute = false, RedirectStandardOutput = true, CreateNoWindow = true, }; using (var p = Process.Start(proc)) { p.WaitForExit(); } var fi = new FileInfo(Path.Combine(outDir, $"{Path.GetFileNameWithoutExtension(filepath)}.{filetype}")); if (!fi.Exists) { return(null); } return(fi.FullName); }
/// <summary> /// Uncooks a single file by hash. /// </summary> /// <param name="hash"></param> /// <param name="outDir"></param> /// <param name="uncookext"></param> /// <returns></returns> public int UncookSingle(ulong hash, DirectoryInfo outDir, EUncookExtension uncookext = EUncookExtension.tga) { using var mmf = MemoryMappedFile.CreateFromFile(Filepath, FileMode.Open, Mmfhash, 0, MemoryMappedFileAccess.Read); return(UncookSingleInner(mmf, hash, outDir, uncookext)); }
public void ConvertToDds(EUncookExtension type) { var testFile = Path.GetFullPath($"Resources/{GetTestFile()}.{type.ToString()}"); Directory.CreateDirectory(Path.GetFullPath("texc")); var bytes = File.ReadAllBytes(testFile); //var blob = new TexconvNative.Blob(); //var len = TexconvNative.ConvertToDds(bytes, ref blob, TexconvNative.ESaveFileTypes.TGA, DXGI_FORMAT.DXGI_FORMAT_UNKNOWN); //var outFile = Path.GetFullPath(Path.Combine("texc", "q204_columbarium_1080p_0.dds")); //File.WriteAllBytes(outFile, blob.GetBytes()); var ms = new MemoryStream(bytes); ms.Seek(0, SeekOrigin.Begin); var r1 = Texconv.ConvertToDds(ms, type, DXGI_FORMAT.DXGI_FORMAT_BC1_UNORM); var outFile1 = Path.GetFullPath(Path.Combine("texc", $"{GetTestFile()}_1.{type}.dds")); File.WriteAllBytes(outFile1, r1); ms.Seek(0, SeekOrigin.Begin); var r3 = Texconv.ConvertToDds(ms, type, DXGI_FORMAT.DXGI_FORMAT_BC3_UNORM); var outFile3 = Path.GetFullPath(Path.Combine("texc", $"{GetTestFile()}_3.{type}.dds")); File.WriteAllBytes(outFile3, r3); ms.Seek(0, SeekOrigin.Begin); var r7 = Texconv.ConvertToDds(ms, type, DXGI_FORMAT.DXGI_FORMAT_BC7_UNORM); var outFile7 = Path.GetFullPath(Path.Combine("texc", $"{GetTestFile()}_7.{type}.dds")); File.WriteAllBytes(outFile7, r7); }
public static bool Convert(string outDir, string filepath, EUncookExtension filetype, EFormat format = EFormat.R8G8B8A8_UNORM, int mipmaps = 0 ) { var logger = ServiceLocator.Default.ResolveType <ILoggerService>(); var proc = new ProcessStartInfo(textconvpath) { WorkingDirectory = Path.GetDirectoryName(textconvpath), Arguments = $" -o \"{outDir}\" -y -f {format} -m {mipmaps} -l -ft {filetype} \"{filepath}\"", UseShellExecute = false, RedirectStandardOutput = true, CreateNoWindow = true, }; using (var p = Process.Start(proc)) { p.WaitForExit(); } var fi = new FileInfo(Path.Combine(outDir, $"{Path.GetFileNameWithoutExtension(filepath)}.{filetype}")); if (!fi.Exists) { logger.LogString($"Could not convert {fi.FullName}.", Logtype.Error); return(false); } return(true); }
public static string Convert(string outDir, string filepath, EUncookExtension filetype, EFormat format = EFormat.R8G8B8A8_UNORM, int mipmaps = 0 ) { string textconvpath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Tools/DDS/texconv.exe"); var argsss = $" -o '{outDir}' -y -f {format} -ft {filetype} '{filepath}'"; var proc = new ProcessStartInfo(textconvpath) { WorkingDirectory = Path.GetDirectoryName(textconvpath), Arguments = $" -o \"{outDir}\" -y -f {format} -m {mipmaps} -l -ft {filetype} \"{filepath}\"", UseShellExecute = false, RedirectStandardOutput = true, CreateNoWindow = true, }; using (var p = Process.Start(proc)) { p.WaitForExit(); } var fi = new FileInfo(Path.Combine(outDir, $"{Path.GetFileNameWithoutExtension(filepath)}.{filetype}")); if (!fi.Exists) { throw new NotImplementedException(); } return(fi.FullName); }
public int ExtractSingle(ulong hash, DirectoryInfo outDir, bool extract = true, bool uncook = false, EUncookExtension uncookext = EUncookExtension.tga) { using var mmf = MemoryMappedFile.CreateFromFile(Filepath, FileMode.Open, Mmfhash, 0, MemoryMappedFileAccess.Read); return(ExtractSingleInner(mmf, hash, outDir, extract, uncook, uncookext)); }
public static void ExportTask(string[] path, EUncookExtension uncookext) { if (path == null || path.Length < 1) { logger.LogString("Please fill in an input path", Logtype.Error); return; } Parallel.ForEach(path, file => { ExportTaskInner(file, uncookext); }); }
public static void UncookTask(string[] path, string outpath, EUncookExtension uext, bool flip, ulong hash, string pattern, string regex) { if (path == null || path.Length < 1) { logger.LogString("Please fill in an input path", Logtype.Error); return; } Parallel.ForEach(path, file => { UncookTaskInner(file, outpath, uext, flip, hash, pattern, regex); }); }
public static void ArchiveTask(string[] path, string outpath, bool extract, bool dump, bool list, bool uncook, EUncookExtension uext, ulong hash, string pattern, string regex) { if (path == null || path.Length < 1) { logger.LogString("Please fill in an input path", Logtype.Error); return; } Parallel.ForEach(path, file => { ArchiveTaskInner(file, outpath, extract, dump, list, uncook, uext, hash, pattern, regex); }); }
/// <summary> /// Converts texture stream with given extension stream to dds /// </summary> public static byte[] ConvertToDds(Stream stream, EUncookExtension inExtension, DXGI_FORMAT?outFormat = null, bool vflip = false, bool hflip = false) { if (inExtension == EUncookExtension.dds) { throw new NotSupportedException("texture to convert to dds must not be dds iteslf"); } byte[] rentedBuffer = null; try { var offset = 0; var len = checked ((int)stream.Length); rentedBuffer = ArrayPool <byte> .Shared.Rent(len); int readBytes; while (offset < len && (readBytes = stream.Read(rentedBuffer, offset, len - offset)) > 0) { offset += readBytes; } var format = outFormat ?? DXGI_FORMAT.DXGI_FORMAT_UNKNOWN; if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { var buffer = Array.Empty <byte>(); using (var blob = new ManagedBlob()) { var l = TexconvNative.ConvertToDds(rentedBuffer, blob.GetBlob(), ToSaveFormat(inExtension), format, vflip, hflip); buffer = blob.GetBytes(); } return(buffer); } else { throw new NotImplementedException(); } } finally { if (rentedBuffer is object) { ArrayPool <byte> .Shared.Return(rentedBuffer); } } }
/// <summary> /// Exports (Uncooks) a REDEngine file into it's raw counterpart /// </summary> /// <param name="cr2wfile"></param> /// <param name="outpath"></param> public static bool Export(FileInfo cr2wfile, EUncookExtension uncookext = EUncookExtension.dds, bool flip = false) { #region checks if (cr2wfile == null) { return(false); } if (!cr2wfile.Exists) { return(false); } if (cr2wfile.Directory != null && !cr2wfile.Directory.Exists) { return(false); } var ext = Path.GetExtension(cr2wfile.FullName)[1..];
/// <summary> /// Converts a dds stream to another texture file type and returns an image byte array /// </summary> public static unsafe byte[] ConvertToDdsMemory( Stream ms, EUncookExtension filetype, DXGI_FORMAT?format = null, bool vflip = false, bool hflip = false) { byte[] rentedBuffer = null; try { var offset = 0; var len = checked ((int)ms.Length); rentedBuffer = ArrayPool <byte> .Shared.Rent(len); int readBytes; while (offset < len && (readBytes = ms.Read(rentedBuffer, offset, len - offset)) > 0) { offset += readBytes; } var span = new ReadOnlySpan <byte>(rentedBuffer, 0, len); fixed(byte *ptr = span) { var fmt = format != null ? (DirectXTexSharp.DXGI_FORMAT_WRAPPED)format : DirectXTexSharp.DXGI_FORMAT_WRAPPED.DXGI_FORMAT_UNKNOWN; var buffer = DirectXTexSharp.Texconv.ConvertToDdsArray(ptr, span.Length, filetype.ToSaveFormat(), fmt, vflip, hflip); return(buffer); } } finally { if (rentedBuffer is object) { ArrayPool <byte> .Shared.Return(rentedBuffer); } } }
/// <summary> /// Exports (Uncooks) a REDEngine file into it's raw counterpart /// </summary> /// <param name="cr2wfile"></param> /// <param name="outpath"></param> public static bool Export(FileInfo cr2wfile, EUncookExtension uncookext = EUncookExtension.tga) { #region checks if (cr2wfile == null) { return(false); } if (!cr2wfile.Exists) { return(false); } if (cr2wfile.Directory != null && !cr2wfile.Directory.Exists) { return(false); } if (!Enum.GetNames(typeof(ECookedFileFormat)).Contains(cr2wfile.Extension[1..]))
public void ConvertFromDds(EUncookExtension type) { var testFile = Path.GetFullPath($"Resources/{GetTestFile()}.dds"); var bytes = File.ReadAllBytes(testFile); //foreach (var type in Enum.GetValues<EUncookExtension>()) { var outFile = Path.GetFullPath(Path.Combine("texc", $"{GetTestFile()}.{type.ToString()}")); //var blob = new TexconvNative.Blob(); //var len = TexconvNative.ConvertFromDds(bytes, ref blob, Texconv.ToSaveFormat(type)); using var ms = new MemoryStream(bytes); var buffer = Texconv.ConvertFromDds(ms, type); File.WriteAllBytes(outFile, buffer); } }
/// <summary> /// Uncooks all Files to the specified directory. /// </summary> /// <param name="outDir"></param> /// <param name="uncookext"></param> /// <returns></returns> public (List <string>, int) UncookAll(DirectoryInfo outDir, EUncookExtension uncookext = EUncookExtension.tga) { using var pb = new ProgressBar(); using var p1 = pb.Progress.Fork(); int progress = 0; var extractedList = new ConcurrentBag <string>(); var failedList = new ConcurrentBag <string>(); int all = 0; using var mmf = MemoryMappedFile.CreateFromFile(Filepath, FileMode.Open, Mmfhash, 0, MemoryMappedFileAccess.Read); Parallel.For(0, FileCount, new ParallelOptions { MaxDegreeOfParallelism = 8 }, i => { var info = Files.Values.ToList()[i]; if (CanUncook(info.NameHash64)) { Interlocked.Increment(ref all); int uncooked = UncookSingleInner(mmf, info.NameHash64, outDir, uncookext); if (uncooked != 0) { extractedList.Add(info.NameStr); } else { failedList.Add(info.NameStr); } } Interlocked.Increment(ref progress); var perc = progress / (double)FileCount; p1.Report(perc, $"Loading bundle entries: {progress}/{FileCount}"); }); return(extractedList.ToList(), all); }
public BundleFileExtractArgs(string fullpath, EUncookExtension extension = EUncookExtension.tga) { FileName = fullpath; Extension = extension; }
private static void UncookTaskInner(string path, string outpath, EUncookExtension uext, bool flip, ulong hash, string pattern, string regex) { #region checks if (string.IsNullOrEmpty(path)) { logger.LogString("Please fill in an input path", Logtype.Error); return; } var inputFileInfo = new FileInfo(path); var inputDirInfo = new DirectoryInfo(path); if (!inputFileInfo.Exists && !inputDirInfo.Exists) { logger.LogString("Input path does not exist", Logtype.Error); return; } if (inputFileInfo.Exists && inputFileInfo.Extension != ".archive") { logger.LogString("Input file is not an .archive", Logtype.Error); return; } else if (inputDirInfo.Exists && inputDirInfo.GetFiles().All(_ => _.Extension != ".archive")) { logger.LogString("No .archive file to process in the input directory", Logtype.Error); return; } var isDirectory = !inputFileInfo.Exists; var basedir = inputFileInfo.Exists ? new FileInfo(path).Directory : inputDirInfo; #endregion List <FileInfo> archiveFileInfos; if (isDirectory) { var archiveManager = new ArchiveManager(basedir); // TODO: use the manager here? archiveFileInfos = archiveManager.Archives.Select(_ => new FileInfo(_.Value.ArchiveAbsolutePath)).ToList(); } else { archiveFileInfos = new List <FileInfo> { inputFileInfo }; } foreach (var processedarchive in archiveFileInfos) { // get outdirectory DirectoryInfo outDir; if (string.IsNullOrEmpty(outpath)) { outDir = Directory.CreateDirectory(Path.Combine( basedir.FullName, processedarchive.Name.Replace(".archive", ""))); } else { outDir = new DirectoryInfo(outpath); if (!outDir.Exists) { outDir = Directory.CreateDirectory(outpath); } if (inputDirInfo.Exists) { outDir = Directory.CreateDirectory(Path.Combine( outDir.FullName, processedarchive.Name.Replace(".archive", ""))); } } // read archive var ar = new Archive(processedarchive.FullName); // run if (hash != 0) { ar.UncookSingle(hash, outDir, uext, flip); logger.LogString($" {ar.ArchiveAbsolutePath}: Uncooked one file: {hash}", Logtype.Success); } else { var r = ar.UncookAll(outDir, pattern, regex, uext, flip); logger.LogString($" {ar.ArchiveAbsolutePath}: Uncooked {r.Item1.Count}/{r.Item2} files.", Logtype.Success); } } return; }
private void ParseMaterials(CR2WFile cr2w, Stream meshStream, DirectoryInfo outDir, List <Archive> archives, string matRepo, EUncookExtension eUncookExtension = EUncookExtension.dds) { List <string> primaryDependencies = new List <string>(); List <string> materialEntryNames = new List <string>(); List <CMaterialInstance> materialEntries = new List <CMaterialInstance>(); GetMateriaEntries(cr2w, meshStream, ref primaryDependencies, ref materialEntryNames, ref materialEntries, archives); List <string> mlSetupNames = new List <string>(); List <Multilayer_Setup> mlSetups = new List <Multilayer_Setup>(); List <string> mlTemplateNames = new List <string>(); List <Multilayer_LayerTemplate> mlTemplates = new List <Multilayer_LayerTemplate>(); List <HairProfile> HairProfiles = new List <HairProfile>(); List <string> HairProfileNames = new List <string>(); List <string> TexturesList = new List <string>(); var exportArgs = new GlobalExportArgs().Register( new XbmExportArgs() { UncookExtension = eUncookExtension }, new MlmaskExportArgs() { UncookExtension = eUncookExtension } ); for (int i = 0; i < primaryDependencies.Count; i++) { if (Path.GetExtension(primaryDependencies[i]) == ".xbm") { if (!TexturesList.Contains(primaryDependencies[i])) { TexturesList.Add(primaryDependencies[i]); } ulong hash = FNV1A64HashAlgorithm.HashString(primaryDependencies[i]); foreach (Archive ar in archives) { if (ar.Files.ContainsKey(hash)) { if (!File.Exists(Path.Combine(matRepo, primaryDependencies[i].Replace("xbm", exportArgs.Get <XbmExportArgs>().UncookExtension.ToString())))) { if (Directory.Exists(matRepo)) { _modTools.UncookSingle(ar, hash, new DirectoryInfo(matRepo), exportArgs); } } break; } } } if (Path.GetExtension(primaryDependencies[i]) == ".mlmask") { if (!TexturesList.Contains(primaryDependencies[i])) { TexturesList.Add(primaryDependencies[i]); } ulong hash = FNV1A64HashAlgorithm.HashString(primaryDependencies[i]); foreach (Archive ar in archives) { if (ar.Files.ContainsKey(hash)) { if (!File.Exists(Path.Combine(matRepo, primaryDependencies[i].Replace(".mlmask", $"_0.{exportArgs.Get<XbmExportArgs>().UncookExtension.ToString()}")))) { if (Directory.Exists(matRepo)) { _modTools.UncookSingle(ar, hash, new DirectoryInfo(matRepo), exportArgs); } } break; } } } if (Path.GetExtension(primaryDependencies[i]) == ".hp") { if (!HairProfileNames.Contains(Path.GetFileName(primaryDependencies[i]))) { HairProfileNames.Add(Path.GetFileName(primaryDependencies[i])); ulong hash = FNV1A64HashAlgorithm.HashString(primaryDependencies[i]); foreach (Archive ar in archives) { if (ar.Files.ContainsKey(hash)) { var ms = new MemoryStream(); ModTools.ExtractSingleToStream(ar, hash, ms); var hp = _wolvenkitFileService.TryReadCr2WFile(ms); HairProfiles.Add(new HairProfile(hp.Chunks[0].Data as CHairProfile, Path.GetFileName(primaryDependencies[i]))); break; } } } } if (Path.GetExtension(primaryDependencies[i]) == ".mlsetup") { ulong hash = FNV1A64HashAlgorithm.HashString(primaryDependencies[i]); foreach (Archive ar in archives) { if (ar.Files.ContainsKey(hash)) { var ms = new MemoryStream(); ModTools.ExtractSingleToStream(ar, hash, ms); var mls = _wolvenkitFileService.TryReadCr2WFile(ms); mlSetupNames.Add(Path.GetFileName(primaryDependencies[i])); mlSetups.Add(mls.Chunks[0].Data as Multilayer_Setup); for (int e = 0; e < mls.Imports.Count; e++) { if (Path.GetExtension(mls.Imports[e].DepotPathStr) == ".xbm") { if (!TexturesList.Contains(mls.Imports[e].DepotPathStr)) { TexturesList.Add(mls.Imports[e].DepotPathStr); } ulong hash1 = FNV1A64HashAlgorithm.HashString(mls.Imports[e].DepotPathStr); foreach (Archive arr in archives) { if (arr.Files.ContainsKey(hash1)) { if (!File.Exists(Path.Combine(matRepo, mls.Imports[e].DepotPathStr.Replace("xbm", exportArgs.Get <XbmExportArgs>().UncookExtension.ToString())))) { if (Directory.Exists(matRepo)) { _modTools.UncookSingle(arr, hash1, new DirectoryInfo(matRepo), exportArgs); } } break; } } } if (Path.GetExtension(mls.Imports[e].DepotPathStr) == ".mltemplate") { ulong hash2 = FNV1A64HashAlgorithm.HashString(mls.Imports[e].DepotPathStr); foreach (Archive arr in archives) { if (arr.Files.ContainsKey(hash2)) { var mss = new MemoryStream(); ModTools.ExtractSingleToStream(arr, hash2, mss); var mlt = _wolvenkitFileService.TryReadCr2WFile(mss); mlTemplateNames.Add(Path.GetFileName(mls.Imports[e].DepotPathStr)); mlTemplates.Add(mlt.Chunks[0].Data as Multilayer_LayerTemplate); for (int eye = 0; eye < mlt.Imports.Count; eye++) { if (!TexturesList.Contains(mlt.Imports[eye].DepotPathStr)) { TexturesList.Add(mlt.Imports[eye].DepotPathStr); } ulong hash3 = FNV1A64HashAlgorithm.HashString(mlt.Imports[eye].DepotPathStr); foreach (Archive arrr in archives) { if (arrr.Files.ContainsKey(hash3)) { if (!File.Exists(Path.Combine(matRepo, mlt.Imports[eye].DepotPathStr.Replace("xbm", exportArgs.Get <XbmExportArgs>().UncookExtension.ToString())))) { if (Directory.Exists(matRepo)) { _modTools.UncookSingle(arrr, hash3, new DirectoryInfo(matRepo), exportArgs); } } break; } } } break; } } } } break; } } } } List <RawMaterial> RawMaterials = new List <RawMaterial>(); for (int i = 0; i < materialEntries.Count; i++) { RawMaterials.Add(ContainRawMaterial(materialEntries[i], materialEntryNames[i], archives)); } List <Setup> MaterialSetups = new List <Setup>(); for (int i = 0; i < mlSetups.Count; i++) { MaterialSetups.Add(new Setup(mlSetups[i], mlSetupNames[i])); } List <Template> MaterialTemplates = new List <Template>(); for (int i = 0; i < mlTemplates.Count; i++) { MaterialTemplates.Add(new Template(mlTemplates[i], mlTemplateNames[i])); } var obj = new { MaterialRepo = matRepo, Materials = RawMaterials, HairProfiles = HairProfiles, MaterialSetups = MaterialSetups, MaterialTemplates = MaterialTemplates }; var settings = new JsonSerializerSettings(); settings.NullValueHandling = NullValueHandling.Ignore; settings.Formatting = Formatting.Indented; string str = JsonConvert.SerializeObject(obj, settings); File.WriteAllLines(Path.Combine(outDir.FullName, "Textures.txt"), TexturesList); File.WriteAllText(Path.Combine(outDir.FullName, "Material.json"), str); }
public bool ExportMeshWithMaterials(Stream meshStream, FileInfo outfile, List <Archive> archives, string matRepo, EUncookExtension eUncookExtension = EUncookExtension.dds, bool isGLBinary = true, bool LodFilter = true) { if (matRepo == null) { throw new Exception("Material Repository Path is not set, Please select a folder in the Material Repository Settings where your textures will output, Generating the complete dump is not required."); } var cr2w = _wolvenkitFileService.TryReadRED4File(meshStream); if (cr2w == null || !cr2w.Chunks.Select(_ => _.Data).OfType <CMesh>().Any() || !cr2w.Chunks.Select(_ => _.Data).OfType <rendRenderMeshBlob>().Any()) { return(false); } DirectoryInfo outDir = new DirectoryInfo(Path.Combine(outfile.DirectoryName, Path.GetFileNameWithoutExtension(outfile.FullName))); MESH.MeshBones meshBones = new MESH.MeshBones(); meshBones.boneCount = cr2w.Chunks.Select(_ => _.Data).OfType <CMesh>().First().BoneNames.Count; if (meshBones.boneCount != 0) // for rigid meshes { meshBones.Names = RIG.GetboneNames(cr2w); meshBones.WorldPosn = MESH.GetMeshBonesPosn(cr2w); } RawArmature Rig = MESH.GetNonParentedRig(meshBones); MemoryStream ms = MESH.GetMeshBufferStream(meshStream, cr2w); MeshesInfo meshinfo = MESH.GetMeshesinfo(cr2w); List <RawMeshContainer> expMeshes = MESH.ContainRawMesh(ms, meshinfo, LodFilter); if (meshBones.boneCount == 0) // for rigid meshes { for (int i = 0; i < expMeshes.Count; i++) { expMeshes[i].weightcount = 0; } } MESH.UpdateMeshJoints(ref expMeshes, Rig, meshBones); ModelRoot model = MESH.RawMeshesToGLTF(expMeshes, Rig); if (!outDir.Exists) { Directory.CreateDirectory(outDir.FullName); } ParseMaterials(cr2w, meshStream, outDir, archives, matRepo, eUncookExtension); if (isGLBinary) { model.SaveGLB(outfile.FullName); } else { model.SaveGLTF(outfile.FullName); } meshStream.Dispose(); meshStream.Close(); return(true); }
public static void ArchiveTask(string path, string outpath, bool extract, bool dump, bool list, bool uncook, EUncookExtension uext, ulong hash) { #region checks if (string.IsNullOrEmpty(path)) { Console.WriteLine("Input file does not exist"); return; } var inputFileInfo = new FileInfo(path); if (!inputFileInfo.Exists) { Console.WriteLine("Input file does not exist"); return; } if (inputFileInfo.Extension != ".archive") { Console.WriteLine("Input file is not an .archive"); return; } var indir = new FileInfo(path).Directory; if (indir == null) { return; } #endregion if (extract || dump || list || uncook) { // get outdirectory var outDir = Directory.CreateDirectory(Path.Combine( indir.FullName, inputFileInfo.Name.Replace(".archive", ""))); if (!string.IsNullOrEmpty(outpath)) { outDir = new DirectoryInfo(outpath); if (!outDir.Exists) { Console.WriteLine("Output directory does not exist"); return; } } if (!outDir.Exists) { Directory.CreateDirectory(outDir.FullName); } // read archive var ar = new Archive(inputFileInfo.FullName); // run if (extract || uncook) { if (hash != 0) { ar.ExtractSingle(hash, outDir, extract, uncook, uext); } else { Console.WriteLine($"{path}: Found {ar.FileCount} files."); var result = ar.ExtractAll(outDir, extract, uncook, uext); Console.WriteLine($"{path}: Extracted {result.Count} files."); } } if (dump) { ar.DumpInfo(outDir); Console.WriteLine($"Finished dumping {path}."); } if (list) { foreach (var entry in ar.Files) { Console.WriteLine(entry.Value.NameStr); } } } return; }
public static ESaveFileTypes ToSaveFormat(EUncookExtension extension) => extension switch {
private void GenerateMaterialRepo(DirectoryInfo materialRepoDir, EUncookExtension texturesExtension) { var cp77Controller = _gameControllerFactory.GetRed4Controller(); var bm = cp77Controller.GetArchiveManagers(false).OfType <ArchiveManager>().FirstOrDefault(); if (bm == null) { return; } var unbundle = new List <string>() { ".gradient", ".w2mi", ".matlib", ".remt", ".sp", ".hp", ".fp", ".mi", ".mt", ".mlsetup", ".mltemplate", ".texarray", }; var uncook = new List <string>() { ".xbm", ".mlmask" }; var groupedFiles = bm.GroupedFiles; // unbundle foreach (var(key, fileEntries) in groupedFiles) { if (!unbundle.Contains(key)) { continue; } var fileslist = groupedFiles[key].ToList(); _loggerService.Info($"{key}: Found {fileslist.Count} entries to uncook"); var progress = 0; _progress.Report(0); Parallel.ForEach(fileslist, entry => { var endPath = Path.Combine(materialRepoDir.FullName, entry.Name); var dirpath = Path.GetDirectoryName(endPath); Directory.CreateDirectory(dirpath); using (var fs = new FileStream(endPath, FileMode.Create, FileAccess.Write)) { entry.Extract(fs); } Interlocked.Increment(ref progress); _progress.Report(progress / (float)fileslist.Count); } ); _loggerService.Success($"{key}: Unbundled {fileslist.Count} files."); } // uncook var exportArgs = new GlobalExportArgs().Register( new XbmExportArgs() { UncookExtension = texturesExtension }, new MlmaskExportArgs() { UncookExtension = texturesExtension } ); foreach (var(key, fileEntries) in groupedFiles) { if (!uncook.Contains(key)) { continue; } var fileslist = groupedFiles[key].ToList(); _loggerService.Info($"{key}: Found {fileslist.Count} entries to uncook"); var progress = 0; _progress.Report(0); Parallel.ForEach(fileslist, entry => { _modTools.UncookSingle(entry.Archive as Archive, entry.Key, materialRepoDir, exportArgs); Interlocked.Increment(ref progress); _progress.Report(progress / (float)fileslist.Count); } ); _loggerService.Success($"{key}: Uncooked {fileslist.Count} files."); } }
public bool ExportMeshWithMaterials(Stream meshStream, FileInfo outfile, List <Archive> archives, string matRepo, EUncookExtension eUncookExtension = EUncookExtension.dds, bool isGLBinary = true, bool LodFilter = true) { if (matRepo == null) { throw new Exception("Material Repository Path is not set, Please select a folder in the Material Repository Settings where your textures will output, Generating the complete dump is not required."); } var cr2w = _wolvenkitFileService.ReadRed4File(meshStream); if (cr2w == null || cr2w.RootChunk is not CMesh cMesh || cMesh.RenderResourceBlob.Chunk is not rendRenderMeshBlob rendblob) { return(false); } using var ms = new MemoryStream(rendblob.RenderBuffer.Buffer.GetBytes()); var meshesinfo = MeshTools.GetMeshesinfo(rendblob, cr2w); var expMeshes = MeshTools.ContainRawMesh(ms, meshesinfo, LodFilter); MeshTools.UpdateSkinningParamCloth(ref expMeshes, meshStream, cr2w); var Rig = MeshTools.GetOrphanRig(rendblob, cr2w); var model = MeshTools.RawMeshesToGLTF(expMeshes, Rig); ParseMaterials(cr2w, meshStream, outfile, archives, matRepo, eUncookExtension); if (isGLBinary) { model.SaveGLB(outfile.FullName); } else { model.SaveGLTF(outfile.FullName); } meshStream.Dispose(); meshStream.Close(); return(true); }
private void ParseMaterials(CR2WFile cr2w, Stream meshStream, FileInfo outfile, List <Archive> archives, string matRepo, EUncookExtension eUncookExtension = EUncookExtension.dds) { var primaryDependencies = new List <string>(); var materialEntryNames = new List <string>(); var materialEntries = new List <CMaterialInstance>(); GetMateriaEntries(cr2w, meshStream, ref primaryDependencies, ref materialEntryNames, ref materialEntries, archives); var mlSetupNames = new List <string>(); var mlTemplateNames = new List <string>(); var HairProfileNames = new List <string>(); var TexturesList = new List <string>(); var exportArgs = new GlobalExportArgs().Register( new XbmExportArgs() { UncookExtension = eUncookExtension }, new MlmaskExportArgs() { UncookExtension = eUncookExtension.ToMlmaskUncookExtension() } ); for (var i = 0; i < primaryDependencies.Count; i++) { if (Path.GetExtension(primaryDependencies[i]) == ".xbm") { if (!TexturesList.Contains(primaryDependencies[i])) { TexturesList.Add(primaryDependencies[i]); } var hash = FNV1A64HashAlgorithm.HashString(primaryDependencies[i]); foreach (var ar in archives) { if (ar.Files.ContainsKey(hash)) { if (!File.Exists(Path.Combine(matRepo, Path.ChangeExtension(primaryDependencies[i], "." + exportArgs.Get <XbmExportArgs>().UncookExtension.ToString())))) { if (Directory.Exists(matRepo)) { UncookSingle(ar, hash, new DirectoryInfo(matRepo), exportArgs); } } break; } } } if (Path.GetExtension(primaryDependencies[i]) == ".mlmask") { if (!TexturesList.Contains(primaryDependencies[i])) { TexturesList.Add(primaryDependencies[i]); } var hash = FNV1A64HashAlgorithm.HashString(primaryDependencies[i]); foreach (var ar in archives) { if (ar.Files.ContainsKey(hash)) { if (!File.Exists(Path.Combine(matRepo, primaryDependencies[i].Replace(".mlmask", $"_0.{exportArgs.Get<XbmExportArgs>().UncookExtension.ToString()}")))) { if (Directory.Exists(matRepo)) { UncookSingle(ar, hash, new DirectoryInfo(matRepo), exportArgs); } } break; } } } if (Path.GetExtension(primaryDependencies[i]) == ".hp") { if (!HairProfileNames.Contains(primaryDependencies[i])) { var hash = FNV1A64HashAlgorithm.HashString(primaryDependencies[i]); foreach (var ar in archives) { if (ar.Files.ContainsKey(hash)) { var ms = new MemoryStream(); ExtractSingleToStream(ar, hash, ms); ms.Seek(0, SeekOrigin.Begin); HairProfileNames.Add(primaryDependencies[i]); var path = Path.Combine(matRepo, Path.ChangeExtension(primaryDependencies[i], ".hp.json")); if (!File.Exists(path)) { if (!new FileInfo(path).Directory.Exists) { Directory.CreateDirectory(new FileInfo(path).Directory.FullName); } var hp = _wolvenkitFileService.ReadRed4File(ms); //hp.FileName = primaryDependencies[i]; var dto = new RedFileDto(hp); var doc = RedJsonSerializer.Serialize(dto); File.WriteAllText(path, doc); } break; } } } } if (Path.GetExtension(primaryDependencies[i]) == ".mlsetup") { if (!mlSetupNames.Contains(primaryDependencies[i])) { var hash = FNV1A64HashAlgorithm.HashString(primaryDependencies[i]); foreach (var ar in archives) { if (ar.Files.ContainsKey(hash)) { var ms = new MemoryStream(); ExtractSingleToStream(ar, hash, ms); ms.Seek(0, SeekOrigin.Begin); var isResource = _wolvenkitFileService.IsCR2WFile(ms); if (!isResource) { throw new InvalidParsingException("not a cr2w file"); } using var reader = new CR2WReader(ms); _ = reader.ReadFile(out var mls, false); mlSetupNames.Add(primaryDependencies[i]); var path = Path.Combine(matRepo, Path.ChangeExtension(primaryDependencies[i], ".mlsetup.json")); if (!File.Exists(path)) { if (!new FileInfo(path).Directory.Exists) { Directory.CreateDirectory(new FileInfo(path).Directory.FullName); } //mls.FileName = primaryDependencies[i]; var dto = new RedFileDto(mls); var doc = RedJsonSerializer.Serialize(dto); File.WriteAllText(path, doc); } for (var e = 0; e < reader.ImportsList.Count; e++) { if (Path.GetExtension(reader.ImportsList[e].DepotPath) == ".xbm") { if (!TexturesList.Contains(reader.ImportsList[e].DepotPath)) { TexturesList.Add(reader.ImportsList[e].DepotPath); } var hash1 = FNV1A64HashAlgorithm.HashString(reader.ImportsList[e].DepotPath); foreach (var arr in archives) { if (arr.Files.ContainsKey(hash1)) { if (!File.Exists(Path.Combine(matRepo, Path.ChangeExtension(reader.ImportsList[e].DepotPath, "." + exportArgs.Get <XbmExportArgs>().UncookExtension.ToString())))) { if (Directory.Exists(matRepo)) { UncookSingle(arr, hash1, new DirectoryInfo(matRepo), exportArgs); } } break; } } } if (Path.GetExtension(reader.ImportsList[e].DepotPath) == ".mltemplate") { if (!mlTemplateNames.Contains(reader.ImportsList[e].DepotPath)) { var hash2 = FNV1A64HashAlgorithm.HashString(reader.ImportsList[e].DepotPath); foreach (var arr in archives) { if (arr.Files.ContainsKey(hash2)) { var mss = new MemoryStream(); ExtractSingleToStream(arr, hash2, mss); mss.Seek(0, SeekOrigin.Begin); var mlt = _wolvenkitFileService.ReadRed4File(mss); mlTemplateNames.Add(reader.ImportsList[e].DepotPath); var path1 = Path.Combine(matRepo, Path.ChangeExtension(reader.ImportsList[e].DepotPath, ".mltemplate.json")); if (!File.Exists(path1)) { if (!new FileInfo(path1).Directory.Exists) { Directory.CreateDirectory(new FileInfo(path1).Directory.FullName); } //mlt.FileName = mls.Imports[e].DepotPath; var dto1 = new RedFileDto(mlt); var doc1 = RedJsonSerializer.Serialize(dto1); File.WriteAllText(path1, doc1); } for (var eye = 0; eye < reader.ImportsList.Count; eye++) { if (!TexturesList.Contains(reader.ImportsList[eye].DepotPath)) { TexturesList.Add(reader.ImportsList[eye].DepotPath); } var hash3 = FNV1A64HashAlgorithm.HashString(reader.ImportsList[eye].DepotPath); foreach (var arrr in archives) { if (arrr.Files.ContainsKey(hash3)) { if (!File.Exists(Path.Combine(matRepo, Path.ChangeExtension(reader.ImportsList[eye].DepotPath, "." + exportArgs.Get <XbmExportArgs>().UncookExtension.ToString())))) { if (Directory.Exists(matRepo)) { UncookSingle(arrr, hash3, new DirectoryInfo(matRepo), exportArgs); } } break; } } } break; } } } } } break; } } } } } var RawMaterials = new List <RawMaterial>(); var usedMts = new Dictionary <string, CMaterialTemplate>(); for (var i = 0; i < materialEntries.Count; i++) { RawMaterials.Add(ContainRawMaterial(materialEntries[i], materialEntryNames[i], archives, ref usedMts)); } var matTemplates = new List <RawMaterial>(); { var keys = usedMts.Keys.ToList(); for (var i = 0; i < keys.Count; i++) { var rawMat = new RawMaterial { Name = keys[i], Data = new Dictionary <string, object>() }; foreach (var item in usedMts[keys[i]].Parameters[2]) { rawMat.Data.Add(item.Chunk.ParameterName, GetSerializableValue(item.Chunk)); } matTemplates.Add(rawMat); } } var matData = new MatData { MaterialRepo = matRepo, Materials = RawMaterials, TexturesList = TexturesList, MaterialTemplates = matTemplates }; var str = RedJsonSerializer.Serialize(matData); File.WriteAllText(Path.ChangeExtension(outfile.FullName, ".Material.json"), str); }
private static void ArchiveTaskInner(string path, string outpath, bool extract, bool dump, bool list, bool uncook, EUncookExtension uext, bool flip, ulong hash, string pattern, string regex) { #region checks if (string.IsNullOrEmpty(path)) { logger.LogString("Please fill in an input path", Logtype.Error); return; } var inputFileInfo = new FileInfo(path); var inputDirInfo = new DirectoryInfo(path); if (!inputFileInfo.Exists && !inputDirInfo.Exists) { logger.LogString("Input path does not exist", Logtype.Error); return; } if (inputFileInfo.Exists && inputFileInfo.Extension != ".archive") { logger.LogString("Input file is not an .archive", Logtype.Error); return; } else if (inputDirInfo.Exists && inputDirInfo.GetFiles().All(_ => _.Extension != ".archive")) { logger.LogString("No .archive file to process in the input directory", Logtype.Error); return; } var isDirectory = !inputFileInfo.Exists; var basedir = inputFileInfo.Exists ? new FileInfo(path).Directory : inputDirInfo; #endregion if (extract || dump || list || uncook) { List <FileInfo> archiveFileInfos; if (isDirectory) { var archiveManager = new ArchiveManager(basedir); // TODO: use the manager here? archiveFileInfos = archiveManager.Archives.Select(_ => new FileInfo(_.Filepath)).ToList(); } else { archiveFileInfos = new List <FileInfo> { inputFileInfo }; } foreach (var processedarchive in archiveFileInfos) { // get outdirectory DirectoryInfo outDir; if (string.IsNullOrEmpty(outpath)) { outDir = Directory.CreateDirectory(Path.Combine( basedir.FullName, processedarchive.Name.Replace(".archive", ""))); } else { outDir = new DirectoryInfo(outpath); if (!outDir.Exists) { outDir = Directory.CreateDirectory(outpath); } if (inputDirInfo.Exists) { outDir = Directory.CreateDirectory(Path.Combine( outDir.FullName, processedarchive.Name.Replace(".archive", ""))); } } // read archive var ar = new Archive(processedarchive.FullName); // run if (extract || uncook) { if (hash != 0) { if (extract) { ar.ExtractSingle(hash, outDir); logger.LogString($" {ar.Filepath}: Extracted one file: {hash}", Logtype.Success); } if (uncook) { ar.UncookSingle(hash, outDir, uext, flip); logger.LogString($" {ar.Filepath}: Uncooked one file: {hash}", Logtype.Success); } } else { if (extract) { var r = ar.ExtractAll(outDir, pattern, regex); logger.LogString($"{ar.Filepath}: Extracted {r.Item1.Count}/{r.Item2} files.", Logtype.Success); } if (uncook) { var r = ar.UncookAll(outDir, pattern, regex, uext, flip); logger.LogString($" {ar.Filepath}: Uncooked {r.Item1.Count}/{r.Item2} files.", Logtype.Success); } } } if (dump) { File.WriteAllText(Path.Combine(outDir.Parent.FullName, $"{ar.Name}.json"), JsonConvert.SerializeObject(ar, Formatting.Indented, new JsonSerializerSettings() { ReferenceLoopHandling = ReferenceLoopHandling.Ignore, PreserveReferencesHandling = PreserveReferencesHandling.None, TypeNameHandling = TypeNameHandling.None })); logger.LogString($"Finished dumping {processedarchive.FullName}.", Logtype.Success); } if (list) { foreach (var entry in ar.Files) { logger.LogString(entry.Value.FileName, Logtype.Normal); } } } } return; }
private void ParseMaterials(CR2WFile cr2w, Stream meshStream, FileInfo outfile, List <Archive> archives, string matRepo, EUncookExtension eUncookExtension = EUncookExtension.dds) { var settings = new JsonSerializerSettings(); settings.NullValueHandling = NullValueHandling.Ignore; settings.Formatting = Formatting.Indented; List <string> primaryDependencies = new List <string>(); List <string> materialEntryNames = new List <string>(); List <CMaterialInstance> materialEntries = new List <CMaterialInstance>(); GetMateriaEntries(cr2w, meshStream, ref primaryDependencies, ref materialEntryNames, ref materialEntries, archives); List <string> mlSetupNames = new List <string>(); List <string> mlTemplateNames = new List <string>(); List <string> HairProfileNames = new List <string>(); List <string> TexturesList = new List <string>(); var exportArgs = new GlobalExportArgs().Register( new XbmExportArgs() { UncookExtension = eUncookExtension }, new MlmaskExportArgs() { UncookExtension = eUncookExtension } ); for (int i = 0; i < primaryDependencies.Count; i++) { if (Path.GetExtension(primaryDependencies[i]) == ".xbm") { if (!TexturesList.Contains(primaryDependencies[i])) { TexturesList.Add(primaryDependencies[i]); } ulong hash = FNV1A64HashAlgorithm.HashString(primaryDependencies[i]); foreach (Archive ar in archives) { if (ar.Files.ContainsKey(hash)) { if (!File.Exists(Path.Combine(matRepo, Path.ChangeExtension(primaryDependencies[i], "." + exportArgs.Get <XbmExportArgs>().UncookExtension.ToString())))) { if (Directory.Exists(matRepo)) { UncookSingle(ar, hash, new DirectoryInfo(matRepo), exportArgs); } } break; } } } if (Path.GetExtension(primaryDependencies[i]) == ".mlmask") { if (!TexturesList.Contains(primaryDependencies[i])) { TexturesList.Add(primaryDependencies[i]); } ulong hash = FNV1A64HashAlgorithm.HashString(primaryDependencies[i]); foreach (Archive ar in archives) { if (ar.Files.ContainsKey(hash)) { if (!File.Exists(Path.Combine(matRepo, primaryDependencies[i].Replace(".mlmask", $"_0.{exportArgs.Get<XbmExportArgs>().UncookExtension.ToString()}")))) { if (Directory.Exists(matRepo)) { UncookSingle(ar, hash, new DirectoryInfo(matRepo), exportArgs); } } break; } } } if (Path.GetExtension(primaryDependencies[i]) == ".hp") { if (!HairProfileNames.Contains(primaryDependencies[i])) { ulong hash = FNV1A64HashAlgorithm.HashString(primaryDependencies[i]); foreach (Archive ar in archives) { if (ar.Files.ContainsKey(hash)) { var ms = new MemoryStream(); ExtractSingleToStream(ar, hash, ms); var hp = _wolvenkitFileService.TryReadCr2WFile(ms); HairProfileNames.Add(primaryDependencies[i]); string path = Path.Combine(matRepo, Path.ChangeExtension(primaryDependencies[i], ".hp.json")); if (!File.Exists(path)) { if (!new FileInfo(path).Directory.Exists) { Directory.CreateDirectory(new FileInfo(path).Directory.FullName); } var doc = JsonConvert.SerializeObject(new HairProfile(hp.Chunks[0].Data as CHairProfile, Path.GetFileName(primaryDependencies[i])), settings); File.WriteAllText(path, doc); } break; } } } } if (Path.GetExtension(primaryDependencies[i]) == ".mlsetup") { if (!mlSetupNames.Contains(primaryDependencies[i])) { ulong hash = FNV1A64HashAlgorithm.HashString(primaryDependencies[i]); foreach (Archive ar in archives) { if (ar.Files.ContainsKey(hash)) { var ms = new MemoryStream(); ExtractSingleToStream(ar, hash, ms); var mls = _wolvenkitFileService.TryReadCr2WFile(ms); mlSetupNames.Add(primaryDependencies[i]); string path = Path.Combine(matRepo, Path.ChangeExtension(primaryDependencies[i], ".mlsetup.json")); if (!File.Exists(path)) { if (!new FileInfo(path).Directory.Exists) { Directory.CreateDirectory(new FileInfo(path).Directory.FullName); } var doc = JsonConvert.SerializeObject(new Setup(mls.Chunks[0].Data as Multilayer_Setup, Path.GetFileName(primaryDependencies[i])), settings); File.WriteAllText(path, doc); } for (int e = 0; e < mls.Imports.Count; e++) { if (Path.GetExtension(mls.Imports[e].DepotPathStr) == ".xbm") { if (!TexturesList.Contains(mls.Imports[e].DepotPathStr)) { TexturesList.Add(mls.Imports[e].DepotPathStr); } ulong hash1 = FNV1A64HashAlgorithm.HashString(mls.Imports[e].DepotPathStr); foreach (Archive arr in archives) { if (arr.Files.ContainsKey(hash1)) { if (!File.Exists(Path.Combine(matRepo, Path.ChangeExtension(mls.Imports[e].DepotPathStr, "." + exportArgs.Get <XbmExportArgs>().UncookExtension.ToString())))) { if (Directory.Exists(matRepo)) { UncookSingle(arr, hash1, new DirectoryInfo(matRepo), exportArgs); } } break; } } } if (Path.GetExtension(mls.Imports[e].DepotPathStr) == ".mltemplate") { if (!mlTemplateNames.Contains(mls.Imports[e].DepotPathStr)) { ulong hash2 = FNV1A64HashAlgorithm.HashString(mls.Imports[e].DepotPathStr); foreach (Archive arr in archives) { if (arr.Files.ContainsKey(hash2)) { var mss = new MemoryStream(); ExtractSingleToStream(arr, hash2, mss); var mlt = _wolvenkitFileService.TryReadCr2WFile(mss); mlTemplateNames.Add(mls.Imports[e].DepotPathStr); string path1 = Path.Combine(matRepo, Path.ChangeExtension(mls.Imports[e].DepotPathStr, ".mltemplate.json")); if (!File.Exists(path1)) { if (!new FileInfo(path1).Directory.Exists) { Directory.CreateDirectory(new FileInfo(path1).Directory.FullName); } var doc1 = JsonConvert.SerializeObject(new Template(mlt.Chunks[0].Data as Multilayer_LayerTemplate, Path.GetFileName(mls.Imports[e].DepotPathStr)), settings); File.WriteAllText(path1, doc1); } for (int eye = 0; eye < mlt.Imports.Count; eye++) { if (!TexturesList.Contains(mlt.Imports[eye].DepotPathStr)) { TexturesList.Add(mlt.Imports[eye].DepotPathStr); } ulong hash3 = FNV1A64HashAlgorithm.HashString(mlt.Imports[eye].DepotPathStr); foreach (Archive arrr in archives) { if (arrr.Files.ContainsKey(hash3)) { if (!File.Exists(Path.Combine(matRepo, Path.ChangeExtension(mlt.Imports[eye].DepotPathStr, "." + exportArgs.Get <XbmExportArgs>().UncookExtension.ToString())))) { if (Directory.Exists(matRepo)) { UncookSingle(arrr, hash3, new DirectoryInfo(matRepo), exportArgs); } } break; } } } break; } } } } } break; } } } } } List <RawMaterial> RawMaterials = new List <RawMaterial>(); for (int i = 0; i < materialEntries.Count; i++) { RawMaterials.Add(ContainRawMaterial(materialEntries[i], materialEntryNames[i], archives)); } var obj = new { MaterialRepo = matRepo, Materials = RawMaterials, Description = "Following Texture List is for user reference and has no purpose for importing materials", TexturesList }; string str = JsonConvert.SerializeObject(obj, settings); File.WriteAllText(Path.ChangeExtension(outfile.FullName, ".Material.json"), str); }