Exemple #1
0
        public ConsoleFunctions(
            ILoggerService loggerService,
            IHashService hashService,
            IProgressService <double> progress,
            Red4ParserService wolvenkitFileService,
            ModTools modTools,

            IOptions <CommonImportArgs> commonImportArgs,
            IOptions <XbmImportArgs> xbmImportArgs,
            IOptions <MeshImportArgs> meshImportArgs,
            IOptions <XbmExportArgs> xbmExportArgs,
            IOptions <MeshExportArgs> meshExportArgs,
            IOptions <MorphTargetExportArgs> morphTargetExportArgs,
            IOptions <MlmaskExportArgs> mlmaskExportArgs,
            IOptions <WemExportArgs> wemExportArgs
            )
        {
            _loggerService   = loggerService;
            _modTools        = modTools;
            _progressService = progress;
            _hashService     = hashService;

            _commonImportArgs      = commonImportArgs;
            _xbmImportArgs         = xbmImportArgs;
            _meshImportArgs        = meshImportArgs;
            _wolvenkitFileService  = wolvenkitFileService;
            _xbmExportArgs         = xbmExportArgs;
            _meshExportArgs        = meshExportArgs;
            _morphTargetExportArgs = morphTargetExportArgs;
            _mlmaskExportArgs      = mlmaskExportArgs;
            _wemExportArgs         = wemExportArgs;
        }
Exemple #2
0
        private RawMaterial ContainRawMaterial(CMaterialInstance cMaterialInstance, string Name, List <Archive> archives)
        {
            RawMaterial rawMaterial = new RawMaterial();

            rawMaterial.Name         = Name;
            rawMaterial.BaseMaterial = cMaterialInstance.BaseMaterial.DepotPath;

            List <CMaterialInstance> BaseMaterials = new List <CMaterialInstance>();

            string path = cMaterialInstance.BaseMaterial.DepotPath;

            while (!Path.GetExtension(path).Contains("mt"))
            {
                ulong hash = FNV1A64HashAlgorithm.HashString(path);
                foreach (Archive ar in archives)
                {
                    if (ar.Files.ContainsKey(hash))
                    {
                        var ms = new MemoryStream();
                        ModTools.ExtractSingleToStream(ar, hash, ms);
                        var mi = _wolvenkitFileService.TryReadCr2WFile(ms);
                        BaseMaterials.Add(mi.Chunks[0].Data as CMaterialInstance);
                        path = (mi.Chunks[0].Data as CMaterialInstance).BaseMaterial.DepotPath;
                        break;
                    }
                }
            }

            string type = Path.GetFileName(path);

            BaseMaterials.Reverse();
            for (int i = 0; i < BaseMaterials.Count; i++)
            {
                MATERIAL.ContainRawMaterialEnum(ref rawMaterial, BaseMaterials[i], type);
            }

            MATERIAL.ContainRawMaterialEnum(ref rawMaterial, cMaterialInstance, type);
            return(rawMaterial);
        }
        public bool ExportAnim(Stream animStream, List <Archive> archives, FileInfo outfile, bool isGLBinary = true)
        {
            var cr2w = _wolvenkitFileService.TryReadRED4File(animStream);

            if (!cr2w.Chunks.Select(_ => _.Data).OfType <animAnimSet>().Any())
            {
                return(false);
            }
            var blob = cr2w.Chunks.Select(_ => _.Data).OfType <animAnimSet>().First();

            List <MemoryStream> animDataBuffers = new List <MemoryStream>();

            foreach (var chk in blob.AnimationDataChunks)
            {
                UInt16 bufferIdx = chk.Buffer.Buffer.Value;
                var    b         = cr2w.Buffers[bufferIdx - 1];
                animStream.Seek(b.Offset, SeekOrigin.Begin);
                var ms = new MemoryStream();
                animStream.DecompressAndCopySegment(ms, b.DiskSize, b.MemSize);
                animDataBuffers.Add(ms);
            }

            var Rig  = new RawArmature();
            var hash = FNV1A64HashAlgorithm.HashString(blob.Rig.DepotPath);

            foreach (var ar in archives)
            {
                if (ar.Files.ContainsKey(hash))
                {
                    var ms = new MemoryStream();
                    ModTools.ExtractSingleToStream(ar, hash, ms);
                    Rig = RIG.ProcessRig(_wolvenkitFileService.TryReadRED4File(ms));
                    break;
                }
            }

            if (Rig is null)
            {
                return(false);
            }

            if (Rig.BoneCount < 1)
            {
                return(false);
            }

            var model = ModelRoot.CreateModel();
            var skin  = model.CreateSkin();

            skin.BindJoints(RIG.ExportNodes(ref model, Rig).Values.ToArray());

            for (int i = 0; i < blob.Animations.Count; i++)
            {
                var setEntry    = (blob.Animations[i].GetReference().Data as animAnimSetEntry);
                var animAnimDes = (setEntry.Animation.GetReference().Data as animAnimation);
                if (animAnimDes.AnimationType.Value != Enums.animAnimationType.Normal)
                {
                    continue;
                }
                switch (animAnimDes.AnimBuffer.GetReference().REDType)
                {
                case "animAnimationBufferSimd":
                {
                    var animBuff       = (animAnimDes.AnimBuffer.GetReference().Data as animAnimationBufferSimd);
                    var defferedBuffer = new MemoryStream();
                    if (animBuff.InplaceCompressedBuffer.IsSerialized)
                    {
                        var bufferIdx = animBuff.InplaceCompressedBuffer.Buffer.Value;
                        var b         = cr2w.Buffers[bufferIdx - 1];
                        animStream.Seek(b.Offset, SeekOrigin.Begin);
                        animStream.DecompressAndCopySegment(defferedBuffer, b.DiskSize, b.MemSize);
                        var br = new BinaryReader(defferedBuffer);
                        br.BaseStream.Seek(0, SeekOrigin.Begin);
                        if (br.ReadUInt32() == OodleHelper.KARK)
                        {
                            uint size   = br.ReadUInt32();
                            var  input  = br.ReadBytes((int)(br.BaseStream.Length - 8));
                            var  output = new Byte[size];
                            OodleHelper.Decompress(input, output);
                            defferedBuffer = new MemoryStream(output);
                        }
                    }
                    else
                    {
                        var bufferIdx = animBuff.DefferedBuffer.Buffer.Value;
                        var b         = cr2w.Buffers[bufferIdx - 1];
                        animStream.Seek(b.Offset, SeekOrigin.Begin);
                        animStream.DecompressAndCopySegment(defferedBuffer, b.DiskSize, b.MemSize);
                    }
                    defferedBuffer.Seek(0, SeekOrigin.Begin);
                    SIMD.AddAnimationSIMD(ref model, animBuff, animAnimDes.Name.Value, defferedBuffer, animAnimDes);
                }
                break;

                case "animAnimationBufferCompressed":
                {
                    var animBuff       = (animAnimDes.AnimBuffer.GetReference().Data as animAnimationBufferCompressed);
                    var defferedBuffer = new MemoryStream();
                    if (animBuff.InplaceCompressedBuffer.IsSerialized)
                    {
                        var bufferIdx = animBuff.InplaceCompressedBuffer.Buffer.Value;
                        var b         = cr2w.Buffers[bufferIdx - 1];
                        animStream.Seek(b.Offset, SeekOrigin.Begin);
                        animStream.DecompressAndCopySegment(defferedBuffer, b.DiskSize, b.MemSize);
                        var br = new BinaryReader(defferedBuffer);
                        br.BaseStream.Seek(0, SeekOrigin.Begin);
                        if (br.ReadUInt32() == OodleHelper.KARK)
                        {
                            uint size   = br.ReadUInt32();
                            var  input  = br.ReadBytes((int)(br.BaseStream.Length - 8));
                            var  output = new Byte[size];
                            OodleHelper.Decompress(input, output);
                            defferedBuffer = new MemoryStream(output);
                        }
                    }
                    else if (animBuff.DataAddress.IsSerialized)
                    {
                        var    dataAddr = animBuff.DataAddress;
                        Byte[] bytes    = new Byte[dataAddr.ZeInBytes.Value];
                        animDataBuffers[(int)dataAddr.UnkIndex.Value].Seek(dataAddr.FsetInBytes.Value, SeekOrigin.Begin);
                        animDataBuffers[(int)dataAddr.UnkIndex.Value].Read(bytes, 0, (int)dataAddr.ZeInBytes.Value);
                        defferedBuffer = new MemoryStream(bytes);
                    }
                    else if (animBuff.DefferedBuffer.IsSerialized)
                    {
                        var bufferIdx = animBuff.DefferedBuffer.Buffer.Value;
                        var b         = cr2w.Buffers[bufferIdx - 1];
                        animStream.Seek(b.Offset, SeekOrigin.Begin);
                        animStream.DecompressAndCopySegment(defferedBuffer, b.DiskSize, b.MemSize);
                    }
                    defferedBuffer.Seek(0, SeekOrigin.Begin);
                    SPLINE.AddAnimationSpline(ref model, animBuff, animAnimDes.Name.Value, defferedBuffer, animAnimDes);
                }
                break;
                }
            }
            if (isGLBinary)
            {
                model.SaveGLB(outfile.FullName);
            }
            else
            {
                model.SaveGLTF(outfile.FullName);
            }

            return(true);
        }
Exemple #4
0
        public bool ExportAnim(Stream animStream, List <Archive> archives, FileInfo outfile, bool isGLBinary = true)
        {
            var cr2w = _wolvenkitFileService.ReadRed4File(animStream);

            if (cr2w == null || cr2w.RootChunk is not animAnimSet blob)
            {
                return(false);
            }

            var animDataBuffers = new List <MemoryStream>();

            foreach (var chk in blob.AnimationDataChunks)
            {
                var ms = new MemoryStream();
                ms.Write(chk.Buffer.Buffer.GetBytes());

                animDataBuffers.Add(ms);
            }

            var Rig  = new RawArmature();
            var hash = FNV1A64HashAlgorithm.HashString(blob.Rig.DepotPath);

            foreach (var ar in archives)
            {
                if (ar.Files.ContainsKey(hash))
                {
                    var ms = new MemoryStream();
                    ModTools.ExtractSingleToStream(ar, hash, ms);
                    Rig = RIG.ProcessRig(_wolvenkitFileService.ReadRed4File(ms));
                    break;
                }
            }

            if (Rig is null)
            {
                return(false);
            }

            if (Rig.BoneCount < 1)
            {
                return(false);
            }

            var model = ModelRoot.CreateModel();
            var skin  = model.CreateSkin();

            skin.BindJoints(RIG.ExportNodes(ref model, Rig).Values.ToArray());

            for (var i = 0; i < blob.Animations.Count; i++)
            {
                var setEntry    = blob.Animations[i].Chunk;
                var animAnimDes = setEntry.Animation.Chunk;
                if (animAnimDes.AnimationType.Value != Enums.animAnimationType.Normal)
                {
                    continue;
                }

                if (animAnimDes.AnimBuffer.Chunk is animAnimationBufferSimd)
                {
                    var          animBuff = (animAnimDes.AnimBuffer.Chunk as animAnimationBufferSimd);
                    MemoryStream defferedBuffer;
                    if (animBuff.InplaceCompressedBuffer != null)
                    {
                        defferedBuffer = new MemoryStream(animBuff.InplaceCompressedBuffer.Buffer.GetBytes());
                    }
                    else
                    {
                        defferedBuffer = new MemoryStream(animBuff.DefferedBuffer.Buffer.GetBytes());
                    }
                    defferedBuffer.Seek(0, SeekOrigin.Begin);
                    SIMD.AddAnimationSIMD(ref model, animBuff, animAnimDes.Name, defferedBuffer, animAnimDes);
                }
                else if (animAnimDes.AnimBuffer.Chunk is animAnimationBufferCompressed)
                {
                    var animBuff       = (animAnimDes.AnimBuffer.Chunk as animAnimationBufferCompressed);
                    var defferedBuffer = new MemoryStream();
                    if (animBuff.InplaceCompressedBuffer != null)
                    {
                        defferedBuffer = new MemoryStream(animBuff.InplaceCompressedBuffer.Buffer.GetBytes());
                    }
                    else if (animBuff.DataAddress != null)
                    {
                        var dataAddr = animBuff.DataAddress;
                        var bytes    = new byte[dataAddr.ZeInBytes];
                        animDataBuffers[(int)((uint)dataAddr.UnkIndex)].Seek(dataAddr.FsetInBytes, SeekOrigin.Begin);
                        animDataBuffers[(int)((uint)dataAddr.UnkIndex)].Read(bytes, 0, (int)((uint)dataAddr.ZeInBytes));
                        defferedBuffer = new MemoryStream(bytes);
                    }
                    else if (animBuff.DefferedBuffer.Buffer.MemSize > 0)
                    {
                        defferedBuffer.Write(animBuff.DefferedBuffer.Buffer.GetBytes());
                    }
                    defferedBuffer.Seek(0, SeekOrigin.Begin);
                    SPLINE.AddAnimationSpline(ref model, animBuff, animAnimDes.Name, defferedBuffer, animAnimDes);
                }
            }
            if (isGLBinary)
            {
                model.SaveGLB(outfile.FullName);
            }
            else
            {
                model.SaveGLTF(outfile.FullName);
            }

            return(true);
        }
Exemple #5
0
        public bool WriteMatToMesh(ref CR2WFile cr2w, string _matData, List <Archive> archives)
        {
            if (cr2w == null || !cr2w.Chunks.Select(_ => _.Data).OfType <CMesh>().Any() || !cr2w.Chunks.Select(_ => _.Data).OfType <rendRenderMeshBlob>().Any() || cr2w.Buffers.Count < 1)
            {
                return(false);
            }
            var matData = JsonConvert.DeserializeObject <MatData>(_matData);

            var           materialbuffer = new MemoryStream();
            List <UInt32> offsets        = new List <UInt32>();
            List <UInt32> sizes          = new List <UInt32>();
            List <string> names          = new List <string>();

            if (matData.Materials.Count < 1)
            {
                return(false);
            }

            Dictionary <string, CMaterialTemplate> mts = new Dictionary <string, CMaterialTemplate>();

            for (int i = 0; i < matData.Materials.Count; i++)
            {
                var mat = matData.Materials[i];
                names.Add(mat.Name);
                CR2WFile mi = new CR2WFile();
                {
                    var chunk = new CMaterialInstance(mi, null, "CMaterialInstance")
                    {
                        IsSerialized = true
                    };
                    chunk.CookingPlatform = new CEnum <Enums.ECookingPlatform>(mi, chunk, "cookingPlatform")
                    {
                        IsSerialized = true, Value = Enums.ECookingPlatform.PLATFORM_PC
                    };
                    chunk.CookingPlatform.EnumValueList.Add("PLATFORM_PC");
                    chunk.EnableMask = new CBool(mi, chunk, "enableMask")
                    {
                        IsSerialized = true, Value = true
                    };
                    chunk.ResourceVersion = new CUInt8(mi, chunk, "resourceVersion")
                    {
                        IsSerialized = true, Value = 4
                    };
                    chunk.BaseMaterial = new rRef <IMaterial>(mi, chunk, "baseMaterial")
                    {
                        IsSerialized = true, DepotPath = mat.BaseMaterial
                    };
                    chunk.CMaterialInstanceData = new CArray <CVariantSizeNameType>(mi, chunk, "CMaterialInstanceData")
                    {
                        IsSerialized = true
                    };

                    CMaterialTemplate mt = null;
                    if (mts.ContainsKey(mat.MaterialTemplate))
                    {
                        mt = mts[mat.MaterialTemplate];
                    }
                    else
                    {
                        ulong hash = FNV1A64HashAlgorithm.HashString(mat.MaterialTemplate);
                        foreach (Archive ar in archives)
                        {
                            if (ar.Files.ContainsKey(hash))
                            {
                                var ms = new MemoryStream();
                                ModTools.ExtractSingleToStream(ar, hash, ms);
                                mt = _wolvenkitFileService.TryReadRED4File(ms).Chunks.Select(_ => _.Data).OfType <CMaterialTemplate>().First();
                                mts.Add(mat.MaterialTemplate, mt);
                                break;
                            }
                        }
                    }
                    var keys = matData.Materials[i].Data.Keys.ToList();
                    if (mt != null)
                    {
                        for (int j = 0; j < keys.Count; j++)
                        {
                            string typename = null;
                            for (int k = 0; k < mt.Parameters[2].Count; k++)
                            {
                                var refer = mt.Parameters[2][k].GetReference().Data;
                                if ((refer.ChildrEditableVariables[0] as CName).Value == keys[j])
                                {
                                    if (refer.ChildrEditableVariables.Count > 2)
                                    {
                                        typename = refer.ChildrEditableVariables[2].REDType;
                                    }
                                }
                            }
                            if (typename != null)
                            {
                                // remove when setfromobj deserialization is fixed
                                if (typename == "Color")
                                {
                                    CColor_ value0 = new CColor_(new CR2WFile(), null, keys[j]);
                                    value0.IsSerialized = true;
                                    value0.SetFromJObject(matData.Materials[i].Data[keys[j]]);

                                    var    variant = new CVariantSizeNameType(mi, chunk.CMaterialInstanceData, keys[j]);
                                    CColor value   = new CColor(mi, variant, keys[j]);
                                    value.IsSerialized = true;
                                    value.Red          = new CUInt8(mi, value, "Red")
                                    {
                                        IsSerialized = true, Value = value0.Red.Value
                                    };
                                    value.Green = new CUInt8(mi, value, "Green")
                                    {
                                        IsSerialized = true, Value = value0.Green.Value
                                    };
                                    value.Blue = new CUInt8(mi, value, "Blue")
                                    {
                                        IsSerialized = true, Value = value0.Blue.Value
                                    };
                                    value.Alpha = new CUInt8(mi, value, "Alpha")
                                    {
                                        IsSerialized = true, Value = value0.Alpha.Value
                                    };
                                    variant.SetVariant(value);
                                    chunk.CMaterialInstanceData.Add(variant);
                                }
                                else
                                {
                                    var variant = new CVariantSizeNameType(mi, chunk.CMaterialInstanceData, keys[j]);
                                    var value   = CR2WTypeManager.Create(typename, keys[j], mi, variant);
                                    value.IsSerialized = true;
                                    value.SetFromJObject(matData.Materials[i].Data[keys[j]]);
                                    variant.SetVariant(value);
                                    chunk.CMaterialInstanceData.Add(variant);
                                }
                            }
                        }
                    }


                    mi.CreateChunk(chunk, 0);
                }

                offsets.Add((UInt32)materialbuffer.Position);
                var m = new MemoryStream();
                var b = new BinaryWriter(m);
                mi.Write(b);
                materialbuffer.Write(m.ToArray(), 0, (int)m.Length);
                sizes.Add((UInt32)m.Length);
            }

            var blob = cr2w.Chunks.Select(_ => _.Data).OfType <CMesh>().First();

            // remove existing data
            while (blob.MaterialEntries.Count != 0)
            {
                blob.MaterialEntries.Remove(blob.MaterialEntries[blob.MaterialEntries.Count - 1]);
            }
            while (blob.LocalMaterialBuffer.RawDataHeaders.Count != 0)
            {
                blob.LocalMaterialBuffer.RawDataHeaders.Remove(blob.LocalMaterialBuffer.RawDataHeaders[blob.LocalMaterialBuffer.RawDataHeaders.Count - 1]);
            }
            while (blob.PreloadLocalMaterialInstances.Count != 0)
            {
                blob.PreloadLocalMaterialInstances.Remove(blob.PreloadLocalMaterialInstances[blob.PreloadLocalMaterialInstances.Count - 1]);
            }
            while (blob.PreloadExternalMaterials.Count != 0)
            {
                blob.PreloadExternalMaterials.Remove(blob.PreloadExternalMaterials[blob.PreloadExternalMaterials.Count - 1]);
            }
            while (blob.ExternalMaterials.Count != 0)
            {
                blob.ExternalMaterials.Remove(blob.ExternalMaterials[blob.ExternalMaterials.Count - 1]);
            }
            while (blob.LocalMaterialInstances.Count != 0)
            {
                blob.LocalMaterialInstances.Remove(blob.LocalMaterialInstances[blob.LocalMaterialInstances.Count - 1]);
            }
            //
            for (int i = 0; i < names.Count; i++)
            {
                var c = new CMeshMaterialEntry(cr2w, blob.MaterialEntries, Convert.ToString(i))
                {
                    IsSerialized = true,
                };
                c.IsLocalInstance = new CBool(cr2w, c, "isLocalInstance")
                {
                    Value = true, IsSerialized = true
                };
                c.Name = new CName(cr2w, c, "name")
                {
                    Value = names[i], IsSerialized = true
                };
                c.Index = new CUInt16(cr2w, c, "index")
                {
                    Value = (UInt16)i, IsSerialized = true
                };
                blob.MaterialEntries.Add(c);

                var m = new meshLocalMaterialHeader(cr2w, blob.LocalMaterialBuffer.RawDataHeaders, Convert.ToString(i))
                {
                    IsSerialized = true
                };
                m.Offset = new CUInt32(cr2w, m, "offset")
                {
                    Value = offsets[i], IsSerialized = true
                };
                m.Size = new CUInt32(cr2w, m, "size")
                {
                    Value = sizes[i], IsSerialized = true
                };
                blob.LocalMaterialBuffer.RawDataHeaders.Add(m);
            }

            var compressed = new MemoryStream();

            using var buff  = new BinaryWriter(compressed);
            var(zsize, crc) = buff.CompressAndWrite(materialbuffer.ToArray());

            bool check = false;

            check = blob.LocalMaterialBuffer.RawData.IsSerialized;
            if (!check)
            {
                blob.LocalMaterialBuffer.RawData = new DataBuffer(cr2w, blob.LocalMaterialBuffer, "rawData")
                {
                    IsSerialized = true
                };
                blob.LocalMaterialBuffer.RawData.Buffer = new CUInt16(cr2w, blob.LocalMaterialBuffer.RawData, "Buffer")
                {
                    Value = (UInt16)(cr2w.Buffers.Count + 1), IsSerialized = true
                };

                uint idx = (uint)cr2w.Buffers.Count;
                cr2w.Buffers.Add(new CR2WBufferWrapper(new CR2WBuffer()
                {
                    flags    = 0,
                    index    = idx,
                    offset   = 0,
                    diskSize = zsize,
                    memSize  = (UInt32)materialbuffer.Length,
                    crc32    = crc
                }));

                cr2w.Buffers[(int)idx].ReadData(new BinaryReader(compressed));
                cr2w.Buffers[(int)idx].Offset = cr2w.Buffers[(int)idx - 1].Offset + cr2w.Buffers[(int)idx - 1].DiskSize;
            }
            else
            {
                UInt16 p = (blob.LocalMaterialBuffer.RawData.Buffer.Value);
                cr2w.Buffers[p - 1].DiskSize = zsize;
                cr2w.Buffers[p - 1].Crc32    = crc;
                cr2w.Buffers[p - 1].MemSize  = (UInt32)materialbuffer.Length;
                var off = cr2w.Buffers[p - 1].Offset;
                cr2w.Buffers[p - 1].Offset = 0;
                cr2w.Buffers[p - 1].ReadData(new BinaryReader(compressed));
                cr2w.Buffers[p - 1].Offset = off;
            }

            return(true);
        }
Exemple #6
0
        private RawMaterial ContainRawMaterial(CMaterialInstance cMaterialInstance, string Name, List <Archive> archives, ref Dictionary <string, CMaterialTemplate> mts)
        {
            RawMaterial rawMaterial = new RawMaterial();

            rawMaterial.Name         = Name;
            rawMaterial.BaseMaterial = cMaterialInstance.BaseMaterial.DepotPath;

            List <CMaterialInstance> BaseMaterials = new List <CMaterialInstance>();

            string path = cMaterialInstance.BaseMaterial.DepotPath;
            ulong  hash = FNV1A64HashAlgorithm.HashString(path);

            while (!Path.GetExtension(path).Contains("mt"))
            {
                hash = FNV1A64HashAlgorithm.HashString(path);
                foreach (Archive ar in archives)
                {
                    if (ar.Files.ContainsKey(hash))
                    {
                        var ms = new MemoryStream();
                        ModTools.ExtractSingleToStream(ar, hash, ms);
                        var mi = _wolvenkitFileService.TryReadCr2WFile(ms);
                        BaseMaterials.Add(mi.Chunks[0].Data as CMaterialInstance);
                        path = (mi.Chunks[0].Data as CMaterialInstance).BaseMaterial.DepotPath;
                        break;
                    }
                }
            }
            BaseMaterials.Reverse();

            CMaterialTemplate mt = null;

            if (mts.ContainsKey(path))
            {
                mt = mts[path];
            }
            else
            {
                hash = FNV1A64HashAlgorithm.HashString(path);
                foreach (Archive ar in archives)
                {
                    if (ar.Files.ContainsKey(hash))
                    {
                        var ms = new MemoryStream();
                        ModTools.ExtractSingleToStream(ar, hash, ms);
                        mt = _wolvenkitFileService.TryReadRED4File(ms).Chunks.Select(_ => _.Data).OfType <CMaterialTemplate>().First();
                        mts.Add(path, mt);
                        break;
                    }
                }
            }
            rawMaterial.MaterialTemplate = path;

            rawMaterial.Data = new Dictionary <string, object>();
            for (int i = 0; i < mt.UsedParameters[2].Count; i++)
            {
                for (int e = 0; e < mt.Parameters[2].Count; e++)
                {
                    var refer = mt.Parameters[2][e].GetReference().Data;
                    if ((refer.ChildrEditableVariables[0] as CName).Value == mt.UsedParameters[2][i].Name.Value)
                    {
                        // childreditablevars indexing is dangerous(what if someone changes order of vars), just works :D
                        if (refer.ChildrEditableVariables.Count > 2 && refer.ChildrEditableVariables[2].IsSerialized)
                        {
                            if (refer.ChildrEditableVariables[2] is CColor col)
                            {
                                var col_ = new CColor_(col.Cr2wFile as CR2WFile, null, mt.UsedParameters[2][i].Name.Value);
                                col_.Red = new CUInt8(col.Cr2wFile as CR2WFile, col_, "Red")
                                {
                                    Value = col.Red.Value, IsSerialized = true
                                };
                                col_.Green = new CUInt8(col.Cr2wFile as CR2WFile, col_, "Green")
                                {
                                    Value = col.Green.Value, IsSerialized = true
                                };
                                col_.Blue = new CUInt8(col.Cr2wFile as CR2WFile, col_, "Blue")
                                {
                                    Value = col.Blue.Value, IsSerialized = true
                                };
                                col_.Alpha = new CUInt8(col.Cr2wFile as CR2WFile, col_, "Alpha")
                                {
                                    Value = col.Alpha.Value, IsSerialized = true
                                };

                                rawMaterial.Data.Add(mt.UsedParameters[2][i].Name.Value, col_.ToObject());
                            }
                            else
                            {
                                rawMaterial.Data.Add(mt.UsedParameters[2][i].Name.Value, refer.ChildrEditableVariables[2].ToObject());
                            }
                        }
                    }
                }
            }

            BaseMaterials.Add(cMaterialInstance);
            for (int i = 0; i < BaseMaterials.Count; i++)
            {
                for (int e = 0; e < BaseMaterials[i].CMaterialInstanceData.Count; e++)
                {
                    var variant = BaseMaterials[i].CMaterialInstanceData[e].Variant;
                    // remove when tobj serialization is fixed
                    if (variant is CColor col)
                    {
                        var col_ = new CColor_(col.Cr2wFile as CR2WFile, null, BaseMaterials[i].CMaterialInstanceData[e].REDName);
                        col_.Red = new CUInt8(col.Cr2wFile as CR2WFile, col_, "Red")
                        {
                            Value = col.Red.Value, IsSerialized = true
                        };
                        col_.Green = new CUInt8(col.Cr2wFile as CR2WFile, col_, "Green")
                        {
                            Value = col.Green.Value, IsSerialized = true
                        };
                        col_.Blue = new CUInt8(col.Cr2wFile as CR2WFile, col_, "Blue")
                        {
                            Value = col.Blue.Value, IsSerialized = true
                        };
                        col_.Alpha = new CUInt8(col.Cr2wFile as CR2WFile, col_, "Alpha")
                        {
                            Value = col.Alpha.Value, IsSerialized = true
                        };

                        if (rawMaterial.Data.ContainsKey(BaseMaterials[i].CMaterialInstanceData[e].REDName))
                        {
                            rawMaterial.Data[BaseMaterials[i].CMaterialInstanceData[e].REDName] = col_.ToObject();
                        }
                        else
                        {
                            rawMaterial.Data.Add(BaseMaterials[i].CMaterialInstanceData[e].REDName, col_.ToObject());
                        }
                    }
                    else
                    {
                        if (rawMaterial.Data.ContainsKey(BaseMaterials[i].CMaterialInstanceData[e].REDName))
                        {
                            rawMaterial.Data[BaseMaterials[i].CMaterialInstanceData[e].REDName] = variant.ToObject();
                        }
                        else
                        {
                            rawMaterial.Data.Add(BaseMaterials[i].CMaterialInstanceData[e].REDName, variant.ToObject());
                        }
                    }
                }
            }

            return(rawMaterial);
        }