private RedBaseClass ReadChunk(Package04ChunkHeader c) { // needs header offset //Debug.Assert(BaseStream.Position == c.offset); var redTypeName = GetStringValue((ushort)c.typeID); var(type, _) = RedReflection.GetCSTypeFromRedType(redTypeName); if (type == typeof(RedBaseClass)) { throw new TypeNotFoundException(redTypeName); } return(ReadClass(type)); }
public override void WriteClass(RedBaseClass cls) { if (cls is IRedCustomData customCls) { customCls.CustomWrite(this); return; } _writer.Write((byte)0); var typeInfo = RedReflection.GetTypeInfo(cls.GetType()); foreach (var propertyInfo in typeInfo.GetWritableProperties()) { var value = propertyInfo.GetValue(cls); if (!typeInfo.SerializeDefault && RedReflection.IsDefault(cls.GetType(), propertyInfo, value)) { continue; } var redTypeName = RedReflection.GetRedTypeFromCSType(propertyInfo.Type, propertyInfo.Flags.Clone()); CNameRef.Add(_writer.BaseStream.Position, propertyInfo.RedName); _writer.Write(GetStringIndex(propertyInfo.RedName)); CNameRef.Add(_writer.BaseStream.Position, redTypeName); _writer.Write(GetStringIndex(redTypeName)); var sizePos = _writer.BaseStream.Position; _writer.Write(0); Write((IRedType)value); var endPos = _writer.BaseStream.Position; var bytesWritten = (uint)(endPos - sizePos); _writer.BaseStream.Position = sizePos; _writer.Write(bytesWritten); _writer.BaseStream.Position = endPos; } _writer.Write((ushort)0); if (cls is IRedAppendix app) { app.Write(this); } }
public RedBaseClass ReadClass(Type type) { var instance = RedTypeManager.Create(type); var baseOff = BaseStream.Position; var fieldCount = _reader.ReadUInt16(); //var unk = _reader.ReadUInt16(); var fields = BaseStream.ReadStructs <Package04FieldHeader>(fieldCount); foreach (var f in fields) { var varName = GetStringValue(f.nameID); var typeName = GetStringValue(f.typeID); var(fieldType, flags) = RedReflection.GetCSTypeFromRedType(typeName); var prop = RedReflection.GetPropertyByRedName(type, varName); IRedType value; BaseStream.Position = baseOff + f.offset; if (prop == null) { value = Read(fieldType, 0, Flags.Empty); RedReflection.AddDynamicProperty(instance, varName, value); } else { if (fieldType != prop.Type) { var propName = $"{RedReflection.GetRedTypeFromCSType(instance.GetType())}.{varName}"; throw new InvalidRTTIException(propName, prop.Type, fieldType); } value = Read(prop.Type, 0, flags); prop.SetValue(instance, value); } } return(instance); }
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]);
public bool ReadVariable(RedBaseClass cls) { var nameId = _reader.ReadUInt16(); if (nameId == 0) { return(false); } var varName = GetStringValue(nameId); // Read Type var typeId = _reader.ReadUInt16(); var typename = GetStringValue(typeId); // Read Size var sizepos = _reader.BaseStream.Position; var size = _reader.ReadUInt32(); var(type, flags) = RedReflection.GetCSTypeFromRedType(typename); IRedType value; var prop = RedReflection.GetPropertyByRedName(cls.GetType(), varName); if (prop == null) { value = Read(type, size - 4, flags); RedReflection.AddDynamicProperty(cls, varName, value); } else { value = Read(prop.Type, size - 4, prop.Flags.Clone()); var typeInfo = RedReflection.GetTypeInfo(cls.GetType()); var propName = $"{RedReflection.GetRedTypeFromCSType(cls.GetType())}.{varName}"; if (type != prop.Type) { throw new InvalidRTTIException(propName, prop.Type, type); } #if DEBUG if (!typeInfo.SerializeDefault && !prop.SerializeDefault && RedReflection.IsDefault(cls.GetType(), varName, value)) { throw new InvalidParsingException($"Invalid default val for: \"{propName}\""); } #endif prop.SetValue(cls, value); } PostProcess(); return(true); void PostProcess() { if (value is IRedBufferPointer buf) { buf.GetValue().ParentTypes.Add($"{cls.GetType().Name}.{varName}"); } if (value is IRedArray arr) { if (typeof(IRedBufferPointer).IsAssignableFrom(arr.InnerType)) { foreach (IRedBufferPointer entry in arr) { entry.GetValue().ParentTypes.Add($"{cls.GetType().Name}.{varName}"); } } } } }
public void WriteWidgetAttributes(XmlWriter writer, IRedType value, string property = "") { if (property != "") { property += "."; } var childSets = new List <IRedType>(); var pis = RedReflection.GetTypeInfo(value.GetType()).PropertyInfos; pis.Sort((a, b) => a.Name.CompareTo(b.Name)); pis.ForEach((pi) => { IRedType propertyValue; if (pi.RedName == null) { propertyValue = (IRedType)value.GetType().GetProperty(pi.Name).GetValue(value, null); } else { propertyValue = (IRedType)pi.GetValue((RedBaseClass)value); } var redType = RedReflection.GetRedTypeFromCSType(pi.Type); if (!RedReflection.IsDefault(value.GetType(), pi, propertyValue)) { var propertyName = pi.RedName; switch (propertyName) { case "children": case "backendData": case "parentWidget": return; default: break; } switch (propertyValue) { case IRedBaseHandle handle: var resolvedValue = handle.GetValue(); if (resolvedValue is inkWidget widget) { writer.WriteAttributeString(property + propertyName + "Path", widget.GetPath()); } else { WriteWidgetAttributes(writer, resolvedValue, property + propertyName); } break; case inkWidgetReference inkRef: if (inkRef.Widget != null && inkRef.Widget.GetValue() is inkWidget widgetRef) { writer.WriteAttributeString(property + propertyName, widgetRef.GetPath()); } break; case CArray <CHandle <inkIEffect> > : case CArray <CHandle <inkWidgetLogicController> > : case CArray <CHandle <inkUserData> > : childSets.Add(propertyValue); break; case CArray <inkPropertyBinding> ary: //writer.WriteStartElement("bindings"); foreach (var ipb in ary) { //writer.WriteStartElement("propertyBinding"); writer.WriteAttributeString(ipb.PropertyName + ".binding", ipb.StylePath); //writer.WriteEndElement(); } //writer.WriteEndElement(); break; case inkMargin margin: writer.WriteAttributeString(property + propertyName, margin.Left + "," + margin.Top + "," + margin.Right + "," + margin.Bottom); break; case inkUITransform: case inkWidgetLayout: case textWrappingInfo: WriteWidgetAttributes(writer, propertyValue, property + propertyName); break; case LocalizationString lockey: writer.WriteAttributeString(property + propertyName, lockey.Value.ToString()); break; case HDRColor color: writer.WriteAttributeString(property + propertyName, $"color(srgb {color.Red} {color.Green} {color.Blue} / {color.Alpha})"); //writer.WriteAttributeString(property + propertyName + ".Red", color.Red.ToString()); //writer.WriteAttributeString(property + propertyName + ".Green", color.Green.ToString()); //writer.WriteAttributeString(property + propertyName + ".Blue", color.Blue.ToString()); //writer.WriteAttributeString(property + propertyName + ".Alpha", color.Alpha.ToString()); break; case Vector2 vector2: writer.WriteAttributeString(property + propertyName, $"{vector2.X},{vector2.Y}"); //writer.WriteAttributeString(property + propertyName + ".X", vector2.X.ToString()); //writer.WriteAttributeString(property + propertyName + ".Y", vector2.Y.ToString()); break; default: writer.WriteAttributeString(property + propertyName, propertyValue.ToString()); break; } } }); foreach (var childSet in childSets) { switch (childSet) { case CArray <CHandle <inkIEffect> > effects: writer.WriteStartElement("effects"); foreach (var handle in effects) { var effect = handle.GetValue(); if (effect != null) { writer.WriteStartElement(effect.GetType().Name); WriteWidgetAttributes(writer, effect); writer.WriteEndElement(); } } writer.WriteEndElement(); break; case CArray <CHandle <inkWidgetLogicController> > controllers: writer.WriteStartElement("secondaryControllers"); foreach (var handle in controllers) { var controller = handle.GetValue(); if (controller != null) { writer.WriteStartElement(controller.GetType().Name); WriteWidgetAttributes(writer, controller); writer.WriteEndElement(); } } writer.WriteEndElement(); break; case CArray <CHandle <inkUserData> > ary: writer.WriteStartElement("userData"); foreach (var handle in ary) { var item = handle.GetValue(); if (item != null) { writer.WriteStartElement(item.GetType().Name); WriteWidgetAttributes(writer, item); writer.WriteEndElement(); } } writer.WriteEndElement(); break; } } }