protected object ParseProperty(CR2WBinaryReader br, Type proptype) { //Basic / Value Types switch (proptype.Name) { case "Byte": return(br.ReadByte()); case "UInt16": return(br.ReadUInt16()); case "UInt32": return(br.ReadUInt32()); case "UInt64": return(br.ReadUInt64()); case "SByte": return(br.ReadSByte()); case "Int16": return(br.ReadInt16()); case "Int32": return(br.ReadInt32()); case "Int64": return(br.ReadInt64()); case "Boolean": return(br.ReadBoolean()); case "Single": return(br.ReadSingle()); case "String": return(br.ReadString()); case "Double": return(br.ReadDouble()); case "CName": return(br.ReadCName()); case "CGUID": return(br.ReadCGUID()); case "IdTag": return(br.ReadIdTag()); case "TagList": return(br.ReadTagList()); case "EngineTransform": return(br.ReadEngineTransform()); case "EngineQsTransform": return(br.ReadEngineQsTransform()); case "CDateTime": return(br.ReadCDateTime()); } //Parse Enumerators if (proptype.IsEnum) { return(br.ReadEnumerator(proptype)); } //Parse Generic Types (Array, Soft, Ptr, Handle) if (proptype.IsGenericType) { var instance = Activator.CreateInstance(proptype); var genprop = proptype.GetTypeInfo().GenericTypeArguments[0]; if (proptype.GetGenericTypeDefinition() == typeof(Array <>)) { var length = br.ReadUInt32(); for (int i = 0; i < length; i++) { var value = ParseProperty(br, genprop); proptype.GetMethod("Add").Invoke(instance, new[] { value }); } } else if (proptype.GetGenericTypeDefinition() == typeof(Soft <>)) { var id = br.ReadUInt16() - 1; if (br.resources[id].type != genprop.Name) { throw new InvalidOperationException($"Soft type mismatch. Expected Type: {genprop.Name}. Type Read: {br.resources[id].type}."); } proptype.GetProperty("DepotPath").SetValue(instance, br.resources[id].path); proptype.GetProperty("Flags").SetValue(instance, br.resources[id].flags); } else if (proptype.GetGenericTypeDefinition() == typeof(Ptr <>)) { var id = br.ReadUInt32(); proptype.GetProperty("Index").SetValue(instance, id); } else if (proptype.GetGenericTypeDefinition() == typeof(Handle <>)) { var id = br.ReadInt32(); if (id >= 0) { proptype.GetProperty("HandleType").SetValue(instance, EHandleType.ReferenceHandle); proptype.GetProperty("Index").SetValue(instance, id); } else { id *= -1; proptype.GetProperty("HandleType").SetValue(instance, EHandleType.ResourceHandle); proptype.GetProperty("DepotPath").SetValue(instance, br.resources[id - 1].path); proptype.GetProperty("Flags").SetValue(instance, br.resources[id - 1].flags); } } return(instance); } //Parse classes if (proptype.IsClass || proptype.IsDefined(typeof(REDClassAttribute))) { var instance = Activator.CreateInstance(proptype); ParseClass(br, instance); return(instance); } //Any Unknown Type //Should be impossible to reach if all types get covered above. return(null); }