/// <summary> /// Exports (Uncooks) a physical REDengine file into its raw file /// </summary> /// <param name="cr2wfile"></param> /// <param name="args"></param> /// <param name="basedir"></param> /// <param name="rawoutdir"></param> public bool Export(FileInfo cr2wfile, GlobalExportArgs args, DirectoryInfo basedir = null, DirectoryInfo rawoutdir = null, ECookedFileFormat[] forcebuffers = null) { #region checks if (cr2wfile is null or { Exists : false })
/// <summary> /// Uncooks a single file by hash. This will both extract and uncook the redengine file /// </summary> /// <param name="archive"></param> /// <param name="hash"></param> /// <param name="outDir"></param> /// <param name="rawOutDir"></param> /// <param name="args"></param> /// <param name="forcebuffers"></param> /// <returns></returns> public bool UncookSingle( Archive archive, ulong hash, DirectoryInfo outDir, GlobalExportArgs args, DirectoryInfo rawOutDir = null, ECookedFileFormat[] forcebuffers = null) { if (!archive.Files.ContainsKey(hash)) { return(false); } #region unbundle main file using var cr2WStream = new MemoryStream(); ExtractSingleToStream(archive, hash, cr2WStream); if (archive.Files[hash] is FileEntry entry) { var relFileFullName = entry.FileName; if (string.IsNullOrEmpty(Path.GetExtension(relFileFullName))) { relFileFullName += ".bin"; } var mainFileInfo = new FileInfo(Path.Combine(outDir.FullName, $"{relFileFullName}")); // write mainFile if (!WolvenTesting.IsTesting) { if (mainFileInfo.Directory != null) { Directory.CreateDirectory(mainFileInfo.Directory.FullName); } using var fs = new FileStream(mainFileInfo.FullName, FileMode.Create, FileAccess.Write); cr2WStream.Seek(0, SeekOrigin.Begin); cr2WStream.CopyTo(fs); } #endregion unbundle main file #region extract buffers var hasBuffers = (entry.SegmentsEnd - entry.SegmentsStart) > 1; if (!hasBuffers) { return(true); } // uncook main file buffers to raw out dir if (rawOutDir is null or { Exists : false })
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); }
private void ExportTaskInner(string path, string outDir, EUncookExtension?uext, bool?flip, ECookedFileFormat[] forcebuffers) { #region checks if (string.IsNullOrEmpty(path)) { _loggerService.Warning("Please fill in an input path."); return; } if (!string.IsNullOrEmpty(outDir) && !Directory.Exists(outDir)) { _loggerService.Warning("Please fill in a valid outdirectory path."); return; } var inputFileInfo = new FileInfo(path); var inputDirInfo = new DirectoryInfo(path); if (!inputFileInfo.Exists && !inputDirInfo.Exists) { _loggerService.Warning("Input path does not exist."); return; } var isDirectory = !inputFileInfo.Exists; var basedir = inputFileInfo.Exists ? new FileInfo(path).Directory : inputDirInfo; #endregion checks var filesToExport = isDirectory ? inputDirInfo.GetFiles("*", SearchOption.AllDirectories).ToList() : new List <FileInfo> { inputFileInfo }; // create extract arguments var exportArgs = new GlobalExportArgs().Register( _xbmExportArgs.Value, _meshExportArgs.Value, _morphTargetExportArgs.Value, _mlmaskExportArgs.Value, _wemExportArgs.Value, _animationExportArgs.Value ); if (flip != null) { exportArgs.Get <XbmExportArgs>().Flip = flip.Value; } if (uext != null) { exportArgs.Get <XbmExportArgs>().UncookExtension = uext.Value; exportArgs.Get <MlmaskExportArgs>().UncookExtension = uext.Value.ToMlmaskUncookExtension(); } var archiveDepot = exportArgs.Get <MeshExportArgs>().ArchiveDepot; if (!string.IsNullOrEmpty(archiveDepot) && Directory.Exists(archiveDepot)) { _archiveManager.LoadFromFolder(new DirectoryInfo(archiveDepot)); exportArgs.Get <MeshExportArgs>().Archives = _archiveManager.Archives.Items.Cast <Archive>().ToList(); exportArgs.Get <MorphTargetExportArgs>().Archives = _archiveManager.Archives.Items.Cast <Archive>().ToList(); exportArgs.Get <AnimationExportArgs>().Archives = _archiveManager.Archives.Items.Cast <Archive>().ToList(); } else { archiveDepot = exportArgs.Get <MorphTargetExportArgs>().ArchiveDepot; if (!string.IsNullOrEmpty(archiveDepot) && Directory.Exists(archiveDepot)) { _archiveManager.LoadFromFolder(new DirectoryInfo(archiveDepot)); exportArgs.Get <MeshExportArgs>().Archives = _archiveManager.Archives.Items.Cast <Archive>().ToList(); exportArgs.Get <MorphTargetExportArgs>().Archives = _archiveManager.Archives.Items.Cast <Archive>().ToList(); exportArgs.Get <AnimationExportArgs>().Archives = _archiveManager.Archives.Items.Cast <Archive>().ToList(); } else { archiveDepot = exportArgs.Get <AnimationExportArgs>().ArchiveDepot; if (!string.IsNullOrEmpty(archiveDepot) && Directory.Exists(archiveDepot)) { _archiveManager.LoadFromFolder(new DirectoryInfo(archiveDepot)); exportArgs.Get <MeshExportArgs>().Archives = _archiveManager.Archives.Items.Cast <Archive>().ToList(); exportArgs.Get <MorphTargetExportArgs>().Archives = _archiveManager.Archives.Items.Cast <Archive>().ToList(); exportArgs.Get <AnimationExportArgs>().Archives = _archiveManager.Archives.Items.Cast <Archive>().ToList(); } } } foreach (var fileInfo in filesToExport) { var di = string.IsNullOrEmpty(outDir) ? null : new DirectoryInfo(outDir); if (_modTools.Export(fileInfo, exportArgs, basedir, di, forcebuffers)) { _loggerService.Success($"Successfully exported {path}."); } else { _loggerService.Error($"Failed to export {path}."); } } return; }
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."); } }
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 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); }
//[DataRow(ECookedFileFormat.mlmask)] //// [DataRow(ECookedFileFormat.morphtarget)] //[DataRow(ECookedFileFormat.texarray)] //[DataRow(ECookedFileFormat.wem)] //[DataRow(ECookedFileFormat.xbm)] public void Test_Uncook(ECookedFileFormat extension) { Environment.SetEnvironmentVariable("WOLVENKIT_ENVIRONMENT", "Testing", EnvironmentVariableTarget.Process); var ext = $".{extension.ToString()}"; var infiles = s_groupedFiles[ext].ToList(); var modtools = ServiceLocator.Default.ResolveType <ModTools>(); var resultDir = new DirectoryInfo(Path.Combine(Environment.CurrentDirectory, s_testResultsDirectory, "temp")); if (!resultDir.Exists) { Directory.CreateDirectory(resultDir.FullName); } var logDir = new DirectoryInfo(Path.Combine(Environment.CurrentDirectory, s_testResultsDirectory, "logs")); if (!logDir.Exists) { Directory.CreateDirectory(logDir.FullName); } var exportArgs = new GlobalExportArgs().Register( new XbmExportArgs() { UncookExtension = EUncookExtension.png, Flip = false } ); var uncookfails = new List <FileEntry>(); // random tests var random = new Random(); var limit = Math.Min(int.Parse(s_config.GetSection(s_LIMIT).Value), infiles.Count); var filesToTest = infiles.OrderBy(a => random.Next()).Take(limit).ToList(); Parallel.ForEach(filesToTest, fileEntry => //foreach (var fileEntry in filesToTest) { // skip files without buffers var hasBuffers = (fileEntry.SegmentsEnd - fileEntry.SegmentsStart) > 1; if (!hasBuffers) { //continue; return; } // uncook var resUncook = modtools.UncookSingle(fileEntry.Archive as Archive, fileEntry.Key, resultDir, exportArgs, resultDir); if (!resUncook) { uncookfails.Add(fileEntry); } } ); if (uncookfails.Count > 0) { foreach (var fileEntry in uncookfails) { Console.WriteLine($"Failed to uncook - {fileEntry.FileName}"); } } Assert.AreEqual(limit, limit - uncookfails.Count); }
public void Test_ImportExport(ECookedFileFormat extension) { var ext = $".{extension.ToString()}"; var infiles = s_groupedFiles[ext].ToList(); var modtools = ServiceLocator.Default.ResolveType <ModTools>(); var resultDir = new DirectoryInfo(Path.Combine(Environment.CurrentDirectory, s_testResultsDirectory, "temp")); if (!resultDir.Exists) { Directory.CreateDirectory(resultDir.FullName); } var logDir = new DirectoryInfo(Path.Combine(Environment.CurrentDirectory, s_testResultsDirectory, "logs")); if (!logDir.Exists) { Directory.CreateDirectory(logDir.FullName); } var isKeep = bool.Parse(s_config.GetSection(s_KEEP).Value); var isettings = new GlobalImportArgs().Register( new XbmImportArgs() { Keep = isKeep }, new MeshImportArgs() { Keep = isKeep }, new CommonImportArgs() { Keep = isKeep } ); var esettings = new GlobalExportArgs(); var uncookfails = new List <FileEntry>(); var importfails = new List <FileEntry>(); var equalfails = new List <FileEntry>(); // random tests var random = new Random(); var limit = Math.Min(int.Parse(s_config.GetSection(s_LIMIT).Value), infiles.Count); var filesToTest = infiles.OrderBy(a => random.Next()).Take(limit).ToList(); for (var i = 0; i < filesToTest.Count; i++) { var fileEntry = filesToTest[i]; // skip files without buffers var hasBuffers = (fileEntry.SegmentsEnd - fileEntry.SegmentsStart) > 1; if (!hasBuffers) { continue; } var ar = fileEntry.Archive as Archive; using var cr2wstream = new MemoryStream(); ar.CopyFileToStream(cr2wstream, fileEntry.NameHash64, false); var originalBytes = cr2wstream.ToByteArray(); // uncook var resUncook = modtools.UncookSingle(fileEntry.Archive as Archive, fileEntry.Key, resultDir, esettings, resultDir); if (!resUncook) { uncookfails.Add(fileEntry); Cleanup(); continue; } // rebuild var allfiles = resultDir.GetFiles("*", SearchOption.AllDirectories); var rawfile = allfiles.FirstOrDefault(_ => _.Extension != ext); if (rawfile == null) { Assert.Fail($"No raw file found in {resultDir}"); } var redrelative = new RedRelativePath(rawfile.Directory, rawfile.Name); var resImport = modtools.Import(redrelative, isettings); if (!resImport) { importfails.Add(fileEntry); Cleanup(); continue; } // compare var redfile = allfiles.FirstOrDefault(_ => _.Extension == ext); if (redfile == null) { Assert.Fail($"No red file found in {resultDir}"); } var newbytes = File.ReadAllBytes(redfile.FullName); if (!originalBytes.SequenceEqual(newbytes)) { equalfails.Add(fileEntry); var filename = Path.GetFileName(fileEntry.FileName); var dbgOriginalFile = Path.Combine(logDir.FullName, filename); var dbgNewFile = Path.Combine(logDir.FullName, $"{filename}.new"); File.WriteAllBytes(dbgOriginalFile, originalBytes); File.WriteAllBytes(dbgNewFile, newbytes); } else { } // clean temp dir Cleanup(); } if (uncookfails.Count > 0) { foreach (var fileEntry in uncookfails) { Console.WriteLine($"Failed to uncook - {fileEntry.FileName}"); } } if (importfails.Count > 0) { foreach (var fileEntry in importfails) { Console.WriteLine($"Failed to import - {fileEntry.FileName}"); } } if (equalfails.Count > 0) { foreach (var fileEntry in equalfails) { Console.WriteLine($"Not binary equal - {fileEntry.FileName}"); } } Assert.AreEqual(0, uncookfails.Count + importfails.Count + equalfails.Count); // cleanup var allf = resultDir.GetFiles("*", SearchOption.AllDirectories); foreach (var fileInfo in allf) { fileInfo.Delete(); } var alld = resultDir.GetDirectories(); foreach (var directoryInfo in alld) { directoryInfo.Delete(true); } void Cleanup() { var allfiles = resultDir.GetFiles("*", SearchOption.AllDirectories); try { foreach (var fileInfo in allfiles) { fileInfo.Delete(); } } catch (Exception e) { Console.WriteLine(e); throw; } } }
private void UncookTaskInner(string path, string outpath, string rawOutDir, EUncookExtension?uext, bool?flip, ulong hash, string pattern, string regex, bool unbundle, ECookedFileFormat[] forcebuffers) { #region checks if (string.IsNullOrEmpty(path)) { _loggerService.Warning("Please fill in an input path."); return; } var inputFileInfo = new FileInfo(path); var inputDirInfo = new DirectoryInfo(path); if (!inputFileInfo.Exists && !inputDirInfo.Exists) { _loggerService.Warning("Input path does not exist."); return; } if (inputFileInfo.Exists && inputFileInfo.Extension != ".archive") { _loggerService.Warning("Input file is not an .archive."); return; } else if (inputDirInfo.Exists && inputDirInfo.GetFiles().All(_ => _.Extension != ".archive")) { _loggerService.Warning("No .archive file to process in the input directory"); return; } var isDirectory = !inputFileInfo.Exists; var basedir = inputFileInfo.Exists ? new FileInfo(path).Directory : inputDirInfo; #endregion checks var exportArgs = new GlobalExportArgs().Register( _xbmExportArgs.Value, _meshExportArgs.Value, _morphTargetExportArgs.Value, _mlmaskExportArgs.Value, _wemExportArgs.Value ); if (flip != null) { exportArgs.Get <XbmExportArgs>().Flip = flip.Value; } if (uext != null) { exportArgs.Get <XbmExportArgs>().UncookExtension = uext.Value; exportArgs.Get <MlmaskExportArgs>().UncookExtension = uext.Value; } var archiveDepot = exportArgs.Get <MeshExportArgs>().ArchiveDepot; if (!string.IsNullOrEmpty(archiveDepot) && Directory.Exists(archiveDepot)) { _archiveManager.LoadFromFolder(new DirectoryInfo(archiveDepot)); exportArgs.Get <MeshExportArgs>().Archives = _archiveManager.Archives.Items.Cast <Archive>().ToList(); exportArgs.Get <MorphTargetExportArgs>().Archives = _archiveManager.Archives.Items.Cast <Archive>().ToList(); exportArgs.Get <AnimationExportArgs>().Archives = _archiveManager.Archives.Items.Cast <Archive>().ToList(); } else { archiveDepot = exportArgs.Get <MorphTargetExportArgs>().ArchiveDepot; if (!string.IsNullOrEmpty(archiveDepot) && Directory.Exists(archiveDepot)) { _archiveManager.LoadFromFolder(new DirectoryInfo(archiveDepot)); exportArgs.Get <MeshExportArgs>().Archives = _archiveManager.Archives.Items.Cast <Archive>().ToList(); exportArgs.Get <MorphTargetExportArgs>().Archives = _archiveManager.Archives.Items.Cast <Archive>().ToList(); exportArgs.Get <AnimationExportArgs>().Archives = _archiveManager.Archives.Items.Cast <Archive>().ToList(); } else { archiveDepot = exportArgs.Get <AnimationExportArgs>().ArchiveDepot; if (!string.IsNullOrEmpty(archiveDepot) && Directory.Exists(archiveDepot)) { _archiveManager.LoadFromFolder(new DirectoryInfo(archiveDepot)); exportArgs.Get <MeshExportArgs>().Archives = _archiveManager.Archives.Items.Cast <Archive>().ToList(); exportArgs.Get <MorphTargetExportArgs>().Archives = _archiveManager.Archives.Items.Cast <Archive>().ToList(); exportArgs.Get <AnimationExportArgs>().Archives = _archiveManager.Archives.Items.Cast <Archive>().ToList(); } } } List <FileInfo> archiveFileInfos; if (isDirectory) { _archiveManager.LoadFromFolder(basedir); archiveFileInfos = _archiveManager.Archives.Items.Select(_ => new FileInfo(_.ArchiveAbsolutePath)).ToList(); } else { archiveFileInfos = new List <FileInfo> { inputFileInfo }; } foreach (var fileInfo in archiveFileInfos) { // get outdirectory DirectoryInfo outDir; if (string.IsNullOrEmpty(outpath)) { outDir = new DirectoryInfo(Path.Combine( basedir.FullName, fileInfo.Name.Replace(".archive", ""))); } else { outDir = new DirectoryInfo(outpath); if (!outDir.Exists) { outDir = new DirectoryInfo(outpath); } } DirectoryInfo rawOutDirInfo = null; if (string.IsNullOrEmpty(rawOutDir)) { rawOutDirInfo = outDir; } else { rawOutDirInfo = new DirectoryInfo(rawOutDir); if (!rawOutDirInfo.Exists) { rawOutDirInfo = new DirectoryInfo(rawOutDir); } } // read archive var ar = Red4ParserServiceExtensions.ReadArchive(fileInfo.FullName, _hashService); // run if (hash != 0) { _modTools.UncookSingle(ar, hash, outDir, exportArgs, rawOutDirInfo, forcebuffers); _loggerService.Success($" {ar.ArchiveAbsolutePath}: Uncooked one file: {hash}"); } else { _modTools.UncookAll(ar, outDir, exportArgs, unbundle, pattern, regex, rawOutDirInfo, forcebuffers); } } return; }
private void ParseMaterials(CR2WFile cr2w, Stream meshStream, FileInfo outfile, List <Archive> archives, string matRepo, EUncookExtension eUncookExtension = EUncookExtension.dds) { var settings = new JsonSerializerSettings() { 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); 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 hp = _wolvenkitFileService.TryReadCr2WFile(ms); hp.FileName = primaryDependencies[i]; var dto = new RedFileDto(hp); var doc = JsonConvert.SerializeObject(dto, 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); } mls.FileName = primaryDependencies[i]; var dto = new RedFileDto(mls); var doc = JsonConvert.SerializeObject(dto, 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); } mlt.FileName = mls.Imports[e].DepotPathStr; var dto1 = new RedFileDto(mlt); var doc1 = JsonConvert.SerializeObject(dto1, 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>(); Dictionary <string, CMaterialTemplate> usedMts = new Dictionary <string, CMaterialTemplate>(); for (int i = 0; i < materialEntries.Count; i++) { RawMaterials.Add(ContainRawMaterial(materialEntries[i], materialEntryNames[i], archives, ref usedMts)); } List <RawMaterial> matTemplates = new List <RawMaterial>(); { var keys = usedMts.Keys.ToList(); for (int i = 0; i < keys.Count; i++) { var rawMat = new RawMaterial(); rawMat.Name = keys[i]; rawMat.Data = new Dictionary <string, object>(); for (int e = 0; e < usedMts[keys[i]].Parameters[2].Count; e++) { var refer = usedMts[keys[i]].Parameters[2][e].GetReference().Data; if (refer.ChildrEditableVariables.Count > 2) { if (refer.ChildrEditableVariables[2] is Vector4 vec) { vec.X.Value = 0f; vec.Y.Value = 0f; vec.Z.Value = 0f; vec.W.Value = 0f; vec.X.IsSerialized = true; vec.Y.IsSerialized = true; vec.Z.IsSerialized = true; vec.W.IsSerialized = true; } if (refer.ChildrEditableVariables[2] is CFloat flo) { flo.Value = 0f; flo.IsSerialized = true; } if (refer.ChildrEditableVariables[2] is CColor col) { col.Red.Value = 0; col.Green.Value = 0; col.Blue.Value = 0; col.Alpha.Value = 0; col.Red.IsSerialized = true; col.Green.IsSerialized = true; col.Blue.IsSerialized = true; col.Alpha.IsSerialized = true; } if (refer.ChildrEditableVariables[2] is IREDRef dep) { dep.DepotPath = ""; dep.IsSerialized = true; } refer.ChildrEditableVariables[2].IsSerialized = true; rawMat.Data.Add((refer.ChildrEditableVariables[0] as CName).Value, refer.ChildrEditableVariables[2].ToObject()); } } matTemplates.Add(rawMat); } } var matData = new MatData(); matData.MaterialRepo = matRepo; matData.Materials = RawMaterials; matData.TexturesList = TexturesList; matData.MaterialTemplates = matTemplates; string str = JsonConvert.SerializeObject(matData, settings); File.WriteAllText(Path.ChangeExtension(outfile.FullName, ".Material.json"), str); }