public static void WriteClass(string name, HKXClass cls) { WriteLine("namespace HKX2\r\n{"); PushIndent(); foreach (var e in cls.Enums) { if (!IsSubEnum(e.Name) && name != "hknpShapeType" && name != "hkpBvCompressedMeshShape" && name != "hclObjectSpaceMeshMeshDeformOperator" && name != "hclMeshMeshDeformOperator") { WriteEnum(e); WriteLine(""); } } WriteLine("public partial class " + name + (cls.ParentName != null ? " : " + cls.ParentName : " : IHavokObject")); WriteLine("{"); PushIndent(); string virtAbstract = cls.ParentName != null ? "override" : "virtual"; WriteLine($@"public {virtAbstract} uint Signature " + "{ get => " + cls.Signature + "; }"); WriteLine(""); foreach (var e in cls.Enums) { if (IsSubEnum(e.Name) || name == "hknpShapeType" || name == "hkpBvCompressedMeshShape" || name == "hclObjectSpaceMeshMeshDeformOperator" || name == "hclMeshMeshDeformOperator") { WriteEnum(e); WriteLine(""); } } foreach (var m in cls.Members) { if (m.Flags != null && !m.Flags.Contains("SERIALIZE_IGNORED")) { WriteMember(m); } } WriteLine(""); WriteWriterReader(cls, false); WriteLine(""); WriteWriterReader(cls, true); PopIndent(); WriteLine("}"); PopIndent(); WriteLine("}"); }
public static void ParseEnums(XmlNodeList nodes, HKXClass hkclass) { foreach (XmlNode n in nodes) { HKXEnum e = new HKXEnum(); e.Name = n.ReadStringAttribute("name"); foreach (XmlNode c in n.ChildNodes) { string name = c.ReadStringAttribute("name"); int val = c.ReadInt32Attribute("value"); e.EnumValues.Add(name, val); } hkclass.Enums.Add(e); } }
public static void ParseMembers(XmlNodeList nodes, HKXClass hkclass) { foreach (XmlNode n in nodes) { HKXMember m = new HKXMember(); m.Name = n.ReadStringAttribute("name"); m.Offset = n.ReadUInt32Attribute("offset"); m.VType = Enum.Parse <VTYPE>(n.ReadStringAttribute("vtype")); m.VSubType = Enum.Parse <VTYPE>(n.ReadStringAttribute("vsubtype")); m.CType = n.ReadStringAttributeOrDefault("ctype"); m.EType = n.ReadStringAttributeOrDefault("etype"); m.ArraySize = n.ReadUInt32Attribute("arrsize"); m.Flags = n.ReadStringAttribute("flags"); if (m.Flags != null && !m.Flags.Contains("SERIALIZE_IGNORED")) { hkclass.Members.Add(m); } } }
public static HKXClass ParseClass(XmlDocument doc) { var cls = doc.FirstChild; var hkclass = new HKXClass(); hkclass.Signature = cls.ReadUInt32HexAttribute("signature"); hkclass.ParentName = cls.ReadStringAttributeOrDefault("parent"); hkclass.Size = cls.ReadUInt32Attribute("size"); var enums = cls.SelectSingleNode("enums"); if (enums != null) { ParseEnums(enums.ChildNodes, hkclass); } ParseMembers(cls.SelectSingleNode("members").ChildNodes, hkclass); return(hkclass); }
public static void WriteWriterReader(HKXClass cls, bool isWriter) { string virtAbstract = cls.ParentName != null ? "override" : "virtual"; if (isWriter) { WriteLine("public " + virtAbstract + " void Write(PackFileSerializer s, BinaryWriterEx bw)"); } else { WriteLine("public " + virtAbstract + " void Read(PackFileDeserializer des, BinaryReaderEx br)"); } WriteLine("{"); PushIndent(); if (cls.ParentName != null && isWriter) { WriteLine("base.Write(s, bw);"); } else if (cls.ParentName != null) { WriteLine("base.Read(des, br);"); } HKXMember prev = null; for (int i = 0; i < cls.Members.Count; i++) { if (cls.Members[i].Flags.Contains("SERIALIZE_IGNORED")) { continue; } if (cls.Members[i].CType != null && cls.Members[i].CType == "hkxMesh") { continue; } uint prevoffset = prev == null ? cls.StartOffset : (prev.Offset + MemberSize(prev, prev.VType)); if (prevoffset < cls.Members[i].Offset) { WritePadding(cls.Members[i].Offset - prevoffset, isWriter); } prev = cls.Members[i]; var m = cls.Members[i]; // If it's a simple primitive, emit a direct read/write string brPrimitive = GetSimpleType(m.VType); if (brPrimitive != null) { if (m.ArraySize > 0) { for (int j = 0; j < m.ArraySize; j++) { if (isWriter) { WriteLine($@"bw.Write{brPrimitive}(m_{m.Name}_{j});"); } else { WriteLine($@"m_{m.Name}_{j} = br.Read{brPrimitive}();"); } } } else { if (isWriter) { WriteLine($@"bw.Write{brPrimitive}(m_{m.Name});"); } else { WriteLine($@"m_{m.Name} = br.Read{brPrimitive}();"); } } continue; } brPrimitive = GetComplexType(m.VType); if (brPrimitive != null) { if (m.ArraySize > 0) { for (int j = 0; j < m.ArraySize; j++) { if (isWriter) { WriteLine($@"s.Write{brPrimitive}(bw, m_{m.Name}_{j});"); } else { WriteLine($@"m_{m.Name}_{j} = des.Read{brPrimitive}(br);"); } } } else { if (isWriter) { WriteLine($@"s.Write{brPrimitive}(bw, m_{m.Name});"); } else { WriteLine($@"m_{m.Name} = des.Read{brPrimitive}(br);"); } } continue; } // Arrays if (m.VType == VTYPE.TYPE_ARRAY) { brPrimitive = GetSimpleType(m.VSubType); if (brPrimitive == null) { brPrimitive = GetComplexType(m.VSubType); } if (brPrimitive != null) { if (isWriter) { WriteLine($@"s.Write{brPrimitive}Array(bw, m_{m.Name});"); } else { WriteLine($@"m_{m.Name} = des.Read{brPrimitive}Array(br);"); } continue; } else if (m.VSubType == VTYPE.TYPE_STRUCT) { if (isWriter) { WriteLine($@"s.WriteClassArray<{m.CType}>(bw, m_{m.Name});"); } else { WriteLine($@"m_{m.Name} = des.ReadClassArray<{m.CType}>(br);"); } continue; } else if (m.VSubType == VTYPE.TYPE_POINTER) { if (isWriter) { WriteLine($@"s.WriteClassPointerArray<{m.CType}>(bw, m_{m.Name});"); } else { WriteLine($@"m_{m.Name} = des.ReadClassPointerArray<{m.CType}>(br);"); } continue; } WriteLine($@"// Read {m.VSubType} array"); continue; } // Enum if (m.VType == VTYPE.TYPE_ENUM) { brPrimitive = GetEnumType(m.VSubType, m.EType); if (isWriter) { WriteLine($@"bw.Write{brPrimitive}(({ReduceType(m, m.VSubType, true)})m_{m.Name});"); } else { WriteLine($@"m_{m.Name} = ({m.EType})br.Read{brPrimitive}();"); } continue; } // Flags if (m.VType == VTYPE.TYPE_FLAGS) { brPrimitive = GetEnumType(m.VSubType, m.EType); if (isWriter) { WriteLine($@"bw.Write{brPrimitive}(m_{m.Name});"); } else { WriteLine($@"m_{m.Name} = br.Read{brPrimitive}();"); } continue; } // Read inline class if (m.VType == VTYPE.TYPE_STRUCT) { if (m.ArraySize > 0) { for (int j = 0; j < m.ArraySize; j++) { if (isWriter) { WriteLine($@"m_{m.Name}_{j}.Write(s, bw);"); } else { WriteLine($@"m_{m.Name}_{j} = new {m.CType}();"); WriteLine($@"m_{m.Name}_{j}.Read(des, br);"); } } } else { if (isWriter) { WriteLine($@"m_{m.Name}.Write(s, bw);"); } else { WriteLine($@"m_{m.Name} = new {m.CType}();"); WriteLine($@"m_{m.Name}.Read(des, br);"); } } continue; } // Read class pointer if (m.VType == VTYPE.TYPE_POINTER) { if (m.VSubType != VTYPE.TYPE_STRUCT) { throw new Exception("bruh"); } if (m.ArraySize > 0) { for (int j = 0; j < m.ArraySize; j++) { if (isWriter) { WriteLine($@"s.WriteClassPointer<{m.CType}>(bw, m_{m.Name}_{j});"); } else { WriteLine($@"m_{m.Name}_{j} = des.ReadClassPointer<{m.CType}>(br);"); } } } else { if (isWriter) { WriteLine($@"s.WriteClassPointer<{m.CType}>(bw, m_{m.Name});"); } else { WriteLine($@"m_{m.Name} = des.ReadClassPointer<{m.CType}>(br);"); } } continue; } WriteLine($@"// Read {m.VType}"); } var writeEnd = (cls.Members.Count > 0) ? cls.Members.Last().Offset + MemberSize(cls.Members.Last(), cls.Members.Last().VType) : cls.Size - cls.LocalSize; if (writeEnd < cls.Size) { WritePadding(cls.Size - writeEnd, isWriter); } PopIndent(); WriteLine("}"); }