public bool WriteMatToMesh(ref CR2WFile cr2w, string _matData, List <Archive> archives) { if (cr2w == null || cr2w.RootChunk is not CMesh cMesh || cMesh.RenderResourceBlob.Chunk is not rendRenderMeshBlob) { return(false); } var matData = RedJsonSerializer.Deserialize <MatData>(_matData); var materialbuffer = new MemoryStream(); var offsets = new List <uint>(); var sizes = new List <uint>(); var names = new List <string>(); if (matData.Materials.Count < 1) { return(false); } var mts = new Dictionary <string, CMaterialTemplate>(); for (var i = 0; i < matData.Materials.Count; i++) { var mat = matData.Materials[i]; names.Add(mat.Name); var mi = new CR2WFile(); { var chunk = RedTypeManager.Create <CMaterialInstance>(); chunk.CookingPlatform = Enums.ECookingPlatform.PLATFORM_PC; chunk.EnableMask = true; chunk.ResourceVersion = 4; chunk.BaseMaterial = new CResourceReference <IMaterial>() { DepotPath = mat.BaseMaterial }; chunk.Values = new CArray <CKeyValuePair>(); CMaterialTemplate mt = null; if (mts.ContainsKey(mat.MaterialTemplate)) { mt = mts[mat.MaterialTemplate]; } else { var hash = FNV1A64HashAlgorithm.HashString(mat.MaterialTemplate); foreach (var ar in archives) { if (ar.Files.ContainsKey(hash)) { var ms = new MemoryStream(); ExtractSingleToStream(ar, hash, ms); ms.Seek(0, SeekOrigin.Begin); mt = (CMaterialTemplate)_wolvenkitFileService.ReadRed4File(ms).RootChunk; mts.Add(mat.MaterialTemplate, mt); break; } } } var fakeMaterialInstance = new CMaterialInstance() { BaseMaterial = new CResourceReference <IMaterial> { DepotPath = mat.BaseMaterial }, Values = new CArray <CKeyValuePair>() }; var orgChain = GetMaterialChain(fakeMaterialInstance, archives, ref mts); if (mt != null) { foreach (var(key, value) in matData.Materials[i].Data) { var found = false; for (var k = 0; k < mt.Parameters[2].Count; k++) { var refer = mt.Parameters[2][k].Chunk; if (refer.ParameterName == key) { found = true; object convValue = GetMaterialParameterValue(refer.GetType(), value); if (orgChain.valueDict.ContainsKey(refer.ParameterName) && !Equals(orgChain.valueDict[refer.ParameterName], convValue)) { chunk.Values.Add(new CKeyValuePair(refer.ParameterName, (IRedType)convValue)); } } } if (!found) { var wrapper = ((JsonElement)value).Deserialize <MaterialValueWrapper>(); var(type, _) = RedReflection.GetCSTypeFromRedType(wrapper.Type); var nValue = ((JsonElement)wrapper.Value).Deserialize(type, RedJsonSerializer.Options); chunk.Values.Add(new CKeyValuePair(key, (IRedType)nValue)); } } } mi.RootChunk = chunk; } offsets.Add((uint)materialbuffer.Position); using var m = new MemoryStream(); using var writer = new CR2WWriter(m); writer.WriteFile(mi); materialbuffer.Write(m.ToArray(), 0, (int)m.Length); sizes.Add((uint)m.Length); } var blob = (CMesh)cr2w.RootChunk; // remove existing data while (blob.MaterialEntries.Count != 0) { blob.MaterialEntries.Remove(blob.MaterialEntries[^ 1]);
private static void Test_Extension(string extension) { var parsers = _host.Services.GetRequiredService <Red4ParserService>(); var resultDir = Path.Combine(Environment.CurrentDirectory, s_testResultsDirectory); Directory.CreateDirectory(resultDir); foreach (var file in Directory.GetFiles(resultDir)) { File.Delete(file); } var results = new ConcurrentBag <ArchiveTestResult>(); var files = s_groupedFiles[extension].ToList(); #if IS_PARALLEL Parallel.ForEach(files, file => #else foreach (var file in files) #endif { var hash = file.Key; var archive = file.Archive as Archive; ArgumentNullException.ThrowIfNull(archive); try { #region convert to json using var originalMemoryStream = new MemoryStream(); ModTools.ExtractSingleToStream(archive, hash, originalMemoryStream); if (!parsers.TryReadRed4File(originalMemoryStream, out var originalFile)) { #if IS_PARALLEL return; #else continue; #endif } var dto = new RedFileDto(originalFile); var json = RedJsonSerializer.Serialize(dto); if (string.IsNullOrEmpty(json)) { throw new SerializationException(); } #endregion #region convert back from json var newdto = RedJsonSerializer.Deserialize <RedFileDto>(json); if (newdto == null) { throw new SerializationException(); } var newFile = newdto.Data; #endregion #region compare // old file var header = originalFile.MetaData; var objectsend = (int)header.ObjectsEnd; var originalBytes = originalMemoryStream.ToByteArray().Take(objectsend); // write the new file using var newMemoryStream = new MemoryStream(); using var writer = new CR2WWriter(newMemoryStream); writer.WriteFile(newFile); // hack to compare buffers var newBytes = newMemoryStream.ToByteArray(); newMemoryStream.Seek(0, SeekOrigin.Begin); var dbg = parsers.ReadRed4File(newMemoryStream); //var newExportStartOffset = (int)dbg.Chunks.FirstOrDefault().GetOffset(); // var originalExportStartOffset = (int)originalFile.Chunks.FirstOrDefault().GetOffset(); // if (!originalBytes.Skip(160).SequenceEqual(newBytes.Skip(160))) // { // // check again skipping the tables // if (originalExportStartOffset == newExportStartOffset) // { // if (!originalBytes.Skip(originalExportStartOffset).SequenceEqual(newBytes.Skip(newExportStartOffset))) // { //#if WRITE // File.WriteAllBytes(Path.Combine(resultDir, $"{file.Key}.o.bin"), originalBytes.ToArray()); // File.WriteAllBytes(Path.Combine(resultDir, $"{file.Key}.bin"), newBytes.ToArray()); //#endif // throw new SerializationException("Exports not equal"); // } // else // { // } // } // else // { //#if WRITE // File.WriteAllBytes(Path.Combine(resultDir, $"{file.Key}.o.bin"), originalBytes.ToArray()); // File.WriteAllBytes(Path.Combine(resultDir, $"{file.Key}.bin"), newBytes.ToArray()); //#endif // throw new SerializationException("Header not equal"); // } // } // else // { // } #endregion results.Add(new ArchiveTestResult() { ArchiveName = archive.Name, Hash = hash.ToString(), Success = true }); } catch (Exception e) { Console.WriteLine($"{hash} - {e.Message} - {e.StackTrace}"); results.Add(new ArchiveTestResult() { ArchiveName = archive.Name, Hash = hash.ToString(), Success = false, ExceptionType = e.GetType(), Message = $"{e.Message}" }); } #if IS_PARALLEL });
/// <summary> /// Converts a json string to W2RC file /// </summary> /// <param name="json"></param> /// <returns></returns> /// <exception cref="InvalidParsingException"></exception> public static CR2WFile ConvertFromJson(string json) { var dto = RedJsonSerializer.Deserialize <RedFileDto>(json); return(dto.Data); }