public override void Parse(object[] parameters = null) { bool parseFast = false; if (parameters != null && parameters.Length > 0) { parseFast = (bool)parameters[0]; } var CMapDataBlocks = this.ResourceFile.ResourceData.FindBlocks(MetaName.CMapData); if (CMapDataBlocks.Length == 0) { throw new Exception("CMapData block not found !"); } var CMapData = MetaUtils.ConvertData <CMapData>(CMapDataBlocks[0]); this.CMapData = new MCMapData(); if (parseFast) { this.CMapData.ParseFast(this.ResourceFile.ResourceData, CMapData); } else { this.CMapData.Parse(this.ResourceFile.ResourceData, CMapData); } for (int i = 0; i < this.CMapData.Entities.Count; i++) { this.CMapData.Entities[i].ParentIndex = this.CMapData.Entities[i].ParentIndex; } }
private static string GetStringValue(PsoFile pso, PsoStructureEntryInfo entry, byte[] data, int eoffset) { switch (entry.Unk_5h) { default: return(null); case 0: var str0len = (int)((entry.ReferenceKey >> 16) & 0xFFFF); return(Encoding.ASCII.GetString(data, eoffset, str0len).Replace("\0", "")); case 1: case 2: var dataPtr2 = MetaUtils.ConvertData <DataBlockPointer>(data, eoffset); dataPtr2.SwapEnd(); return(PsoUtils.GetString(pso, dataPtr2)); case 3: var charPtr3 = MetaUtils.ConvertData <CharPointer>(data, eoffset); charPtr3.SwapEnd(); var strval = PsoUtils.GetString(pso, charPtr3); return(strval ?? ""); case 7: case 8: MetaName hashVal = (MetaName)MetaUtils.SwapBytes(MetaUtils.ConvertData <uint>(data, eoffset)); return(HashString(hashVal)); } }
public override void Parse(object[] parameters = null) { var CMapTypesBlocks = this.ResourceFile.ResourceData.FindBlocks(MetaName.CMapTypes); if (CMapTypesBlocks.Length == 0) { throw new Exception("CMapTypes block not found !"); } var CMapTypes = MetaUtils.ConvertData <CMapTypes>(CMapTypesBlocks[0]); this.CMapTypes = new MCMapTypes(); this.CMapTypes.Parse(this.ResourceFile.ResourceData, CMapTypes); }
public override void Parse(object[] parameters = null) { var Unk_376833625Blocks = this.ResourceFile.ResourceData.FindBlocks((MetaName)376833625); if (Unk_376833625Blocks.Length == 0) { throw new Exception("Unk_376833625 block not found !"); } var Unk_376833625 = MetaUtils.ConvertData <Unk_376833625>(Unk_376833625Blocks[0]); this.Unk_376833625 = new RageLib.GTA5.ResourceWrappers.PC.Meta.Structures.MUnk_376833625(); this.Unk_376833625.Parse(this.ResourceFile.ResourceData, Unk_376833625); }
private static void WriteNode(StringBuilder sb, int indent, MetaCont cont, int blockId, int offset, XmlTagMode tagMode = XmlTagMode.None, MetaName structName = 0, string metaName = "") { var block = cont.Meta.GetBlock(blockId); if (block == null) { ErrorXml(sb, indent, "Couldn't find block " + blockId + "!"); return; } if (structName == 0) { structName = (MetaName)block.StructureNameHash; } var name = HashString(structName); var data = Array.ConvertAll(block.Data.Data.ToArray(), e => (byte)e); var structInfo = cont.GetStructureInfo(structName); if (structInfo == null) { ErrorXml(sb, indent, "Couldn't find structure info " + name + "!"); return; } if (structInfo.Entries == null) { ErrorXml(sb, indent, "Couldn't find structure info entries for " + name + "!"); return; } switch (tagMode) { case XmlTagMode.Structure: OpenTag(sb, indent, name, true, metaName); break; case XmlTagMode.Item: OpenTag(sb, indent, "Item", true, metaName); break; case XmlTagMode.ItemAndType: OpenTag(sb, indent, "Item type=\"" + name + "\"", true, metaName); break; } var cind = indent + 1; StructureEntryInfo arrEntry = new StructureEntryInfo(); for (int i = 0; i < structInfo.Entries.Count; i++) { var entry = structInfo.Entries[i]; if ((MetaName)entry.EntryNameHash == MetaName.ARRAYINFO) { arrEntry = entry; continue; } var ename = HashString((MetaName)entry.EntryNameHash); var eoffset = offset + entry.DataOffset; switch (entry.DataType) { default: ErrorXml(sb, cind, ename + ": Unexpected entry DataType: " + entry.DataType.ToString()); break; case StructureEntryDataType.Array: WriteArrayNode(sb, cind, cont, data, arrEntry, ename, eoffset); break; case StructureEntryDataType.ArrayOfBytes: WriteParsedArrayOfBytesNode(sb, cind, data, ename, eoffset, entry, arrEntry); break; case StructureEntryDataType.ArrayOfChars: OpenTag(sb, cind, ename, false); uint charArrLen = (uint)entry.ReferenceKey; for (int n = 0; n < charArrLen; n++) { var bidx = eoffset + n; if ((bidx >= 0) && (bidx < data.Length)) { byte b = data[bidx]; if (b == 0) { break; } sb.Append((char)b); } } CloseTag(sb, 0, ename); break; case StructureEntryDataType.Boolean: var boolVal = BitConverter.ToBoolean(data, eoffset); ValueTag(sb, cind, ename, boolVal?"true":"false"); break; case StructureEntryDataType.ByteEnum: var byteEnumVal = data[eoffset]; ValueTag(sb, cind, ename, byteEnumVal.ToString()); break; case StructureEntryDataType.CharPointer: var charPtr = MetaUtils.ConvertData <CharPointer>(data, eoffset); string charStr = MetaUtils.GetString(cont.Meta, charPtr); OneLineTag(sb, cind, ename, charStr); break; case StructureEntryDataType.DataBlockPointer: OpenTag(sb, cind, ename); var dataPtr = MetaUtils.ConvertData <DataBlockPointer>(data, eoffset); ErrorXml(sb, cind + 1, "DataBlockPointer not currently supported here!"); //TODO! ymap occludeModels vertices data is this type! CloseTag(sb, cind, ename); break; case StructureEntryDataType.Float: var floatVal = BitConverter.ToSingle(data, eoffset); ValueTag(sb, cind, ename, floatVal.ToString(CultureInfo.InvariantCulture)); break; case StructureEntryDataType.Float_XYZ: var v3 = MetaUtils.ConvertData <Vector3>(data, eoffset); SelfClosingTag(sb, cind, ename + " x=\"" + v3.X.ToString(CultureInfo.InvariantCulture) + "\" y=\"" + v3.Y.ToString(CultureInfo.InvariantCulture) + "\" z=\"" + v3.Z.ToString(CultureInfo.InvariantCulture) + "\""); break; case StructureEntryDataType.Float_XYZW: var v4 = MetaUtils.ConvertData <Vector4>(data, eoffset); SelfClosingTag(sb, cind, ename + " x=\"" + v4.X.ToString(CultureInfo.InvariantCulture) + "\" y=\"" + v4.Y.ToString(CultureInfo.InvariantCulture) + "\" z=\"" + v4.Z.ToString(CultureInfo.InvariantCulture) + "\" w=\"" + v4.W.ToString(CultureInfo.InvariantCulture) + "\""); break; case StructureEntryDataType.Hash: var hashVal = (MetaName)MetaUtils.ConvertData <uint>(data, eoffset); var hashStr = HashString(hashVal); StringTag(sb, cind, ename, hashStr); break; case StructureEntryDataType.IntEnum: var intEnumVal = BitConverter.ToInt32(data, eoffset); var intEnumStr = GetEnumString(cont, entry, intEnumVal); StringTag(sb, cind, ename, intEnumStr); break; case StructureEntryDataType.IntFlags1: var intFlags1Val = BitConverter.ToInt32(data, eoffset); var intFlags1Str = GetEnumString(cont, entry, intFlags1Val); StringTag(sb, cind, ename, intFlags1Str); break; case StructureEntryDataType.IntFlags2: var intFlags2Val = BitConverter.ToInt32(data, eoffset); var intFlags2Str = GetEnumString(cont, entry, intFlags2Val); StringTag(sb, cind, ename, intFlags2Str); break; case StructureEntryDataType.ShortFlags: var shortFlagsVal = BitConverter.ToInt16(data, eoffset); var shortFlagsStr = shortFlagsVal.ToString(); // GetEnumString(cont, entry, shortFlagsVal); StringTag(sb, cind, ename, shortFlagsStr); break; case StructureEntryDataType.SignedByte: sbyte sbyteVal = (sbyte)data[eoffset]; ValueTag(sb, cind, ename, sbyteVal.ToString()); break; case StructureEntryDataType.SignedInt: var intVal = BitConverter.ToInt32(data, eoffset); ValueTag(sb, cind, ename, intVal.ToString()); break; case StructureEntryDataType.SignedShort: var shortVal = BitConverter.ToInt16(data, eoffset); ValueTag(sb, cind, ename, shortVal.ToString()); break; case StructureEntryDataType.Structure: OpenTag(sb, cind, ename); WriteNode(sb, cind, cont, blockId, eoffset, XmlTagMode.None, (MetaName)entry.ReferenceKey); CloseTag(sb, cind, ename); break; case StructureEntryDataType.StructurePointer: OpenTag(sb, cind, ename); ErrorXml(sb, cind + 1, "StructurePointer not supported here! Tell dexy!"); CloseTag(sb, cind, ename); break; case StructureEntryDataType.UnsignedByte: var byteVal = data[eoffset]; ValueTag(sb, cind, ename, byteVal.ToString()); //ValueTag(sb, cind, ename, "0x" + byteVal.ToString("X").PadLeft(2, '0')); break; case StructureEntryDataType.UnsignedInt: var uintVal = BitConverter.ToUInt32(data, eoffset); switch ((MetaName)entry.EntryNameHash) { default: ValueTag(sb, cind, ename, uintVal.ToString()); break; case MetaName.color: ValueTag(sb, cind, ename, "0x" + uintVal.ToString("X").PadLeft(8, '0')); break; } break; case StructureEntryDataType.UnsignedShort: var ushortVal = BitConverter.ToUInt16(data, eoffset); ValueTag(sb, cind, ename, ushortVal.ToString()); // "0x" + ushortVal.ToString("X").PadLeft(4, '0')); break; } } switch (tagMode) { case XmlTagMode.Structure: CloseTag(sb, indent, name); break; case XmlTagMode.Item: case XmlTagMode.ItemAndType: CloseTag(sb, indent, "Item"); break; } }
private static void WriteArrayNode(StringBuilder sb, int indent, MetaCont cont, byte[] data, StructureEntryInfo arrEntry, string ename, int eoffset) { int aCount = 0; var aind = indent + 1; string arrTag = ename; switch (arrEntry.DataType) { default: ErrorXml(sb, indent, ename + ": Unexpected array entry DataType: " + arrEntry.DataType.ToString()); break; case StructureEntryDataType.Structure: var arrStruc = MetaUtils.ConvertData <Array_Structure>(data, eoffset); var aBlockId = (int)arrStruc.PointerDataId; var aOffset = (int)arrStruc.PointerDataOffset; aCount = arrStruc.Count1; arrTag += " itemType=\"" + HashString((MetaName)arrEntry.ReferenceKey) + "\""; if (aCount > 0) { OpenTag(sb, indent, arrTag); var atyp = cont.GetStructureInfo((MetaName)arrEntry.ReferenceKey); var aBlock = cont.Meta.GetBlock(aBlockId); for (int n = 0; n < aCount; n++) { WriteNode(sb, aind, cont, aBlockId, aOffset, XmlTagMode.Item, (MetaName)arrEntry.ReferenceKey); aOffset += atyp.StructureLength; if ((n < (aCount - 1)) && (aBlock != null) && (aOffset >= aBlock.DataLength)) { aOffset = 0; aBlockId++; aBlock = cont.Meta.GetBlock(aBlockId); } } CloseTag(sb, indent, ename); } else { SelfClosingTag(sb, indent, arrTag); } break; case StructureEntryDataType.StructurePointer: var arrStrucP = MetaUtils.ConvertData <Array_StructurePointer>(data, eoffset); var ptrArr = MetaUtils.GetPointerArray(cont.Meta, arrStrucP); aCount = ptrArr?.Length ?? 0; if (aCount > 0) { OpenTag(sb, indent, arrTag); for (int n = 0; n < aCount; n++) { var ptr = ptrArr[n]; var offset = ptr.Offset; WriteNode(sb, aind, cont, ptr.BlockID, offset, XmlTagMode.ItemAndType); } CloseTag(sb, indent, ename); } else { SelfClosingTag(sb, indent, arrTag); } break; case StructureEntryDataType.UnsignedInt: var arrUint = MetaUtils.ConvertData <Array_uint>(data, eoffset); var uintArr = MetaUtils.ConvertDataArray <uint>(cont.Meta, arrUint.Pointer, arrUint.Count1);; WriteRawArray(sb, uintArr, indent, ename, "uint"); break; case StructureEntryDataType.UnsignedShort: var arrUshort = MetaUtils.ConvertData <Array_ushort>(data, eoffset); var ushortArr = MetaUtils.ConvertDataArray <ushort>(cont.Meta, arrUshort.Pointer, arrUshort.Count1);; WriteRawArray(sb, ushortArr, indent, ename, "ushort"); break; case StructureEntryDataType.UnsignedByte: var arrUbyte = MetaUtils.ConvertData <Array_byte>(data, eoffset); var byteArr = MetaUtils.ConvertDataArray <byte>(cont.Meta, arrUbyte.Pointer, arrUbyte.Count1);; WriteRawArray(sb, byteArr, indent, ename, "byte"); break; case StructureEntryDataType.Float: var arrFloat = MetaUtils.ConvertData <Array_float>(data, eoffset); var floatArr = MetaUtils.ConvertDataArray <float>(cont.Meta, arrFloat.Pointer, arrFloat.Count1);; WriteRawArray(sb, floatArr, indent, ename, "float"); break; case StructureEntryDataType.Float_XYZ: var arrV3 = MetaUtils.ConvertData <Array_Vector3>(data, eoffset); var v4Arr = MetaUtils.ConvertDataArray <Vector4>(cont.Meta, arrV3.Pointer, arrV3.Count1); WriteItemArray(sb, v4Arr, indent, ename, "Vector3/4", FormatVector4); break; case StructureEntryDataType.CharPointer: ErrorXml(sb, indent, "CharPointer ARRAY not supported here!"); break; case StructureEntryDataType.DataBlockPointer: ErrorXml(sb, indent, "DataBlockPointer ARRAY not supported here!"); break; case StructureEntryDataType.Hash: var arrHash = MetaUtils.ConvertData <Array_uint>(data, eoffset); var uintArr2 = MetaUtils.ConvertDataArray <uint>(cont.Meta, arrHash.Pointer, arrHash.Count1); var hashArr = Array.ConvertAll(uintArr2, e => (MetaName)e); WriteItemArray(sb, hashArr, indent, ename, "Hash", FormatHash); break; } }
public static JObject Deamon_GetModelData(DrawableModel model) { var data = new JObject() { ["shaderMapping"] = new JArray(), ["geometries"] = new JArray() }; var jShaderMapping = (JArray)data["shaderMapping"]; var jGeometries = (JArray)data["geometries"]; for (int i = 0; i < model.ShaderMapping.Count; i++) { jShaderMapping.Add(model.ShaderMapping[i].Value); } for (int i = 0; i < model.Geometries.Count; i++) { var geometry = model.Geometries[i]; var jGeometry = new JObject() { ["vertices"] = new JArray(), ["triangles"] = new JArray() }; var jTriangles = (JArray)jGeometry["triangles"]; var jVertices = (JArray)jGeometry["vertices"]; var vertices = new List <Vector3>(); var vb = geometry.VertexData.VertexBytes; var vs = geometry.VertexData.VertexStride; var vc = geometry.VertexData.VertexCount; for (int j = 0; j < vc; j++) { var jVertex = new JObject() { ["type"] = geometry.VertexData.VertexType.ToString() }; switch (geometry.VertexData.VertexType) { case VertexType.Default: { var vt = MetaUtils.ConvertData <VertexTypeDefault>(vb, j * vs); vertices.Add(vt.Position); jVertex["position"] = new JObject() { ["x"] = vt.Position.X, ["y"] = vt.Position.Y, ["z"] = vt.Position.Z }; jVertex["normal"] = new JObject() { ["x"] = vt.Normal.X, ["y"] = vt.Normal.Y, ["z"] = vt.Normal.Z }; jVertex["colour"] = vt.Colour; jVertex["texCoord"] = new JObject() { ["x"] = vt.Texcoord.X, ["y"] = vt.Texcoord.Y }; break; } case VertexType.DefaultEx: { var vt = MetaUtils.ConvertData <VertexTypeDefaultEx>(vb, j * vs); vertices.Add(vt.Position); jVertex["position"] = new JObject() { ["x"] = vt.Position.X, ["y"] = vt.Position.Y, ["z"] = vt.Position.Z }; jVertex["normal"] = new JObject() { ["x"] = vt.Normal.X, ["y"] = vt.Normal.Y, ["z"] = vt.Normal.Z }; jVertex["colour"] = vt.Colour; jVertex["texCoord"] = new JObject() { ["x"] = vt.Texcoord.X, ["y"] = vt.Texcoord.Y }; break; } case VertexType.PNCCT: { var vt = MetaUtils.ConvertData <VertexTypePNCCT>(vb, j * vs); vertices.Add(vt.Position); jVertex["position"] = new JObject() { ["x"] = vt.Position.X, ["y"] = vt.Position.Y, ["z"] = vt.Position.Z }; jVertex["normal"] = new JObject() { ["x"] = vt.Normal.X, ["y"] = vt.Normal.Y, ["z"] = vt.Normal.Z }; jVertex["texCoord"] = new JObject() { ["x"] = vt.Texcoord.X, ["y"] = vt.Texcoord.Y }; break; } case VertexType.PNCCTTTT: { var vt = MetaUtils.ConvertData <VertexTypePNCCTTTT>(vb, j * vs); vertices.Add(vt.Position); jVertex["position"] = new JObject() { ["x"] = vt.Position.X, ["y"] = vt.Position.Y, ["z"] = vt.Position.Z }; jVertex["normal"] = new JObject() { ["x"] = vt.Normal.X, ["y"] = vt.Normal.Y, ["z"] = vt.Normal.Z }; break; } case VertexType.PNCTTTX: { var vt = MetaUtils.ConvertData <VertexTypePNCTTTX>(vb, j * vs); vertices.Add(vt.Position); jVertex["position"] = new JObject() { ["x"] = vt.Position.X, ["y"] = vt.Position.Y, ["z"] = vt.Position.Z }; jVertex["normal"] = new JObject() { ["x"] = vt.Normal.X, ["y"] = vt.Normal.Y, ["z"] = vt.Normal.Z }; jVertex["colour"] = vt.Colour; break; } case VertexType.PNCTTTX_2: { var vt = MetaUtils.ConvertData <VertexTypePNCTTTX_2>(vb, j * vs); vertices.Add(vt.Position); jVertex["position"] = new JObject() { ["x"] = vt.Position.X, ["y"] = vt.Position.Y, ["z"] = vt.Position.Z }; jVertex["normal"] = new JObject() { ["x"] = vt.Normal.X, ["y"] = vt.Normal.Y, ["z"] = vt.Normal.Z }; jVertex["colour"] = vt.Colour; break; } case VertexType.PNCTTTX_3: { var vt = MetaUtils.ConvertData <VertexTypePNCTTTX_3>(vb, j * vs); vertices.Add(vt.Position); jVertex["position"] = new JObject() { ["x"] = vt.Position.X, ["y"] = vt.Position.Y, ["z"] = vt.Position.Z }; jVertex["normal"] = new JObject() { ["x"] = vt.Normal.X, ["y"] = vt.Normal.Y, ["z"] = vt.Normal.Z }; jVertex["colour"] = vt.Colour; break; } case VertexType.PNCTTX: { var vt = MetaUtils.ConvertData <VertexTypePNCTTX>(vb, j * vs); vertices.Add(vt.Position); jVertex["position"] = new JObject() { ["x"] = vt.Position.X, ["y"] = vt.Position.Y, ["z"] = vt.Position.Z }; jVertex["normal"] = new JObject() { ["x"] = vt.Normal.X, ["y"] = vt.Normal.Y, ["z"] = vt.Normal.Z }; jVertex["colour"] = vt.Colour; break; } case VertexType.PNCCTTX: { var vt = MetaUtils.ConvertData <VertexTypePNCCTTX>(vb, j * vs); vertices.Add(vt.Position); jVertex["position"] = new JObject() { ["x"] = vt.Position.X, ["y"] = vt.Position.Y, ["z"] = vt.Position.Z }; jVertex["normal"] = new JObject() { ["x"] = vt.Normal.X, ["y"] = vt.Normal.Y, ["z"] = vt.Normal.Z }; break; } case VertexType.PNCCTTX_2: { var vt = MetaUtils.ConvertData <VertexTypePNCCTTX_2>(vb, j * vs); vertices.Add(vt.Position); jVertex["position"] = new JObject() { ["x"] = vt.Position.X, ["y"] = vt.Position.Y, ["z"] = vt.Position.Z }; jVertex["normal"] = new JObject() { ["x"] = vt.Normal.X, ["y"] = vt.Normal.Y, ["z"] = vt.Normal.Z }; break; } case VertexType.PNCCTTTX: { var vt = MetaUtils.ConvertData <VertexTypePNCCTTTX>(vb, j * vs); vertices.Add(vt.Position); jVertex["position"] = new JObject() { ["x"] = vt.Position.X, ["y"] = vt.Position.Y, ["z"] = vt.Position.Z }; jVertex["normal"] = new JObject() { ["x"] = vt.Normal.X, ["y"] = vt.Normal.Y, ["z"] = vt.Normal.Z }; break; } case VertexType.PNCCTT: { var vt = MetaUtils.ConvertData <VertexTypePNCCTT>(vb, j * vs); vertices.Add(vt.Position); jVertex["position"] = new JObject() { ["x"] = vt.Position.X, ["y"] = vt.Position.Y, ["z"] = vt.Position.Z }; jVertex["normal"] = new JObject() { ["x"] = vt.Normal.X, ["y"] = vt.Normal.Y, ["z"] = vt.Normal.Z }; break; } case VertexType.PNCCTX: { var vt = MetaUtils.ConvertData <VertexTypePNCCTX>(vb, j * vs); vertices.Add(vt.Position); jVertex["position"] = new JObject() { ["x"] = vt.Position.X, ["y"] = vt.Position.Y, ["z"] = vt.Position.Z }; jVertex["normal"] = new JObject() { ["x"] = vt.Normal.X, ["y"] = vt.Normal.Y, ["z"] = vt.Normal.Z }; jVertex["texCoord"] = new JObject() { ["x"] = vt.Texcoord.X, ["y"] = vt.Texcoord.Y }; break; } case VertexType.PTT: { var vt = MetaUtils.ConvertData <VertexTypePTT>(vb, j * vs); vertices.Add(vt.Position); jVertex["position"] = new JObject() { ["x"] = vt.Position.X, ["y"] = vt.Position.Y, ["z"] = vt.Position.Z };; break; } case VertexType.PNC: { var vt = MetaUtils.ConvertData <VertexTypePNC>(vb, j * vs); vertices.Add(vt.Position); jVertex["position"] = new JObject() { ["x"] = vt.Position.X, ["y"] = vt.Position.Y, ["z"] = vt.Position.Z }; jVertex["normal"] = new JObject() { ["x"] = vt.Normal.X, ["y"] = vt.Normal.Y, ["z"] = vt.Normal.Z }; jVertex["colour"] = vt.Colour; break; } case VertexType.PCT: { var vt = MetaUtils.ConvertData <VertexTypePCT>(vb, j * vs); vertices.Add(vt.Position); jVertex["position"] = new JObject() { ["x"] = vt.Position.X, ["y"] = vt.Position.Y, ["z"] = vt.Position.Z }; jVertex["colour"] = vt.Colour; jVertex["texCoord"] = new JObject() { ["x"] = vt.Texcoord.X, ["y"] = vt.Texcoord.Y }; break; } case VertexType.PT: { var vt = MetaUtils.ConvertData <VertexTypePT>(vb, j * vs); vertices.Add(vt.Position); jVertex["position"] = new JObject() { ["x"] = vt.Position.X, ["y"] = vt.Position.Y, ["z"] = vt.Position.Z }; jVertex["texCoord"] = new JObject() { ["x"] = vt.Texcoord.X, ["y"] = vt.Texcoord.Y }; break; } default: break; } jVertices.Add(jVertex); } for (int j = 0; j < geometry.IndexBuffer.Indices.Count - 2; j += 3) { var triangle = new JArray() { geometry.IndexBuffer.Indices[j + 0].Value, geometry.IndexBuffer.Indices[j + 1].Value, geometry.IndexBuffer.Indices[j + 2].Value }; jTriangles.Add(triangle); } jGeometries.Add(jGeometry); } return(data); }
private static void WriteMapNode(StringBuilder sb, int indent, PsoCont cont, int eoffset, PsoStructureEntryInfo entry, PsoStructureInfo structInfo, string ename) { var cind = indent + 1; var data = cont.Pso.DataSection.Data; switch (entry.Unk_5h) { default: ErrorXml(sb, cind, ename + ": Unexpected Map subtype: " + entry.Unk_5h.ToString()); break; case 1: var mapidx1 = entry.ReferenceKey & 0x0000FFFF; var mapidx2 = (entry.ReferenceKey >> 16) & 0x0000FFFF; var mapreftype1 = structInfo.Entries[mapidx2]; var mapreftype2 = structInfo.Entries[mapidx1]; var x1 = MetaUtils.SwapBytes(BitConverter.ToInt32(data, eoffset)); //same as ref key? var x2 = MetaUtils.SwapBytes(BitConverter.ToInt32(data, eoffset + 4)); //0? var x3 = MetaUtils.SwapBytes(BitConverter.ToInt32(data, eoffset + 8)); //pointer? var x4 = MetaUtils.SwapBytes(BitConverter.ToInt32(data, eoffset + 12)); // var x5 = MetaUtils.SwapBytes(BitConverter.ToInt32(data, eoffset + 16)); //count/capacity? var x6 = MetaUtils.SwapBytes(BitConverter.ToInt32(data, eoffset + 20)); // //File.WriteAllText("C:\\CodeWalker.Projects\\testxml.xml", sb.ToString()); if (x1 != 0x1000000) { } if (x2 != 0) { } if (x4 != 0) { } if (x6 != 0) { } var xBlockId = x3 & 0xFFF; var xOffset = (x3 >> 12) & 0xFFFFF; var xCount1 = x5 & 0xFFFF; var xCount2 = (x5 >> 16) & 0xFFFF; //var x1a = x1 & 0xFFF; //block id? for another pointer? //var x1b = (x1 >> 12) & 0xFFFFF; //offset? //var x4u = (uint)x4; //var x4a = x4 & 0xFFF; //block id? //var x4b = (x4 >> 12) & 0xFFFFF; //offset? //var x2h = (MetaHash)(uint)x2; //var x6h = (MetaHash)(uint)x6; //if (x1a > 0) //{ } var xBlock = cont.Pso.GetBlock(xBlockId); if ((xBlock == null) && (xCount1 > 0)) { ErrorXml(sb, cind, ename + ": Couldn't find Map xBlock: " + xBlockId.ToString()); } else { if (xCount1 != xCount2) { } if (xCount1 > 0) { var xStruct = cont.GetStructureInfo((MetaName)xBlock.NameHash); var xOffset1 = xOffset; var xind = indent + 1; var aind = indent + 2; var kEntry = xStruct?.FindEntry(MetaName.Key); var iEntry = xStruct?.FindEntry(MetaName.Item); if ((xStruct == null) && (xBlock.NameHash == 0)) { SelfClosingTag(sb, cind, ename); } else if (xStruct == null) { ErrorXml(sb, aind, ename + ": Map struct type not found: " + HashString((MetaName)xBlock.NameHash)); } else if ((xStruct.IndexInfo == null)) // || (xStruct.IndexInfo.NameHash != MetaName.ARRAYINFO)) { ErrorXml(sb, aind, ename + ": Map struct was missing IndexInfo! " + (xStruct == null ? "" : xStruct.ToString())); } else if ((kEntry == null) || (iEntry == null)) { ErrorXml(sb, aind, ename + ": Map Key/Item entries not found!"); } else if (kEntry.Type != RageLib.GTA5.PSO.DataType.String) { ErrorXml(sb, aind, ename + ": Map Key was not a string!"); } else if (iEntry.Type != RageLib.GTA5.PSO.DataType.Structure) { ErrorXml(sb, aind, ename + ": Map Item was not a structure!"); } else if (iEntry.Unk_5h != 3) { ErrorXml(sb, aind, ename + ": Map Item was not a structure pointer - TODO!"); } else { OpenTag(sb, xind, ename); int xOffset2 = (int)xOffset1; int xCount = xCount1; for (int n = 0; n < xCount; n++) { //WriteNode(sb, aind, cont, xBlockId, xOffset, XmlTagMode.Item, xStruct.IndexInfo.NameHash); int sOffset = xOffset2 + xBlock.Offset; var kOffset = sOffset + kEntry.DataOffset; var iOffset = sOffset + iEntry.DataOffset; var kStr = GetStringValue(cont.Pso, kEntry, data, kOffset); var iPtr = MetaUtils.ConvertData <PsoPOINTER>(data, iOffset); iPtr.SwapEnd(); var iBlock = cont.Pso.GetBlock(iPtr.BlockID); if (iBlock == null) { OpenTag(sb, aind, "Item type=\"" + HashString((MetaName)entry.ReferenceKey) + "\" key=\"" + kStr + "\""); WriteNode(sb, aind, cont, iPtr.BlockID, (int)iPtr.ItemOffset, XmlTagMode.None, (MetaName)entry.ReferenceKey); CloseTag(sb, aind, "Item"); } else { var iStr = "Item type=\"" + HashString((MetaName)iBlock.NameHash) + "\" key=\"" + kStr + "\""; var iStruc = cont.GetStructureInfo((MetaName)iBlock.NameHash); if (iStruc?.EntriesCount == 0) { //SelfClosingTag(sb, aind, iStr); OpenTag(sb, aind, iStr); CloseTag(sb, aind, "Item"); } else { OpenTag(sb, aind, iStr); WriteNode(sb, aind, cont, iPtr.BlockID, (int)iPtr.ItemOffset, XmlTagMode.None); //, (MetaName)entry.ReferenceKey); CloseTag(sb, aind, "Item"); } } xOffset2 += xStruct.StructureLength; if ((n < (xCount - 1)) && (xBlock != null) && (xOffset >= xBlock.Length)) { ErrorXml(sb, aind, "Offset out of range! Count is " + xCount.ToString()); break; //out of range... } } CloseTag(sb, xind, ename); } } else { SelfClosingTag(sb, cind, ename); } } break; } }
private static void WriteNode(StringBuilder sb, int indent, PsoCont cont, int blockId, int offset, XmlTagMode tagMode = XmlTagMode.None, MetaName structName = 0) { var block = cont.Pso.GetBlock(blockId); if (block == null) { ErrorXml(sb, indent, "Couldn't find block " + blockId + "!"); return; } var boffset = offset + block.Offset; if (structName == 0) { structName = (MetaName)block.NameHash; } var name = HashString(structName); var data = cont.Pso.DataSection.Data; var structInfo = cont.GetStructureInfo(structName); if (structInfo == null) { ErrorXml(sb, indent, "Couldn't find structure info " + name + "!"); return; } if (structInfo.Entries == null) { ErrorXml(sb, indent, "Couldn't find structure info entries for " + name + "!"); return; } switch (tagMode) { case XmlTagMode.Structure: OpenTag(sb, indent, name); break; case XmlTagMode.Item: OpenTag(sb, indent, "Item"); break; case XmlTagMode.ItemAndType: OpenTag(sb, indent, "Item type=\"" + name + "\""); break; } var cind = indent + 1; for (int i = 0; i < structInfo.Entries.Count; i++) { var entry = structInfo.Entries[i]; if ((MetaName)entry.EntryNameHash == MetaName.ARRAYINFO) { continue; } var ename = HashString((MetaName)entry.EntryNameHash); var eoffset = boffset + entry.DataOffset; switch (entry.Type) { default: ErrorXml(sb, cind, ename + ": Unexpected entry DataType: " + entry.Type.ToString()); break; case RageLib.GTA5.PSO.DataType.Array: WriteArrayNode(sb, cind, cont, blockId, offset, entry, structInfo, ename); break; case RageLib.GTA5.PSO.DataType.Bool: var boolVal = BitConverter.ToBoolean(data, eoffset); ValueTag(sb, cind, ename, boolVal ? "true" : "false"); break; case RageLib.GTA5.PSO.DataType.SByte: //was LONG_01h //signed byte? //var long1Val = MetaUtils.SwapBytes(BitConverter.ToUInt64(data, eoffset)); //ValueTag(sb, cind, ename, long1Val.ToString()); var byte1Val = (sbyte)data[eoffset]; ValueTag(sb, cind, ename, byte1Val.ToString()); break; case RageLib.GTA5.PSO.DataType.UByte: var byte2Val = data[eoffset]; ValueTag(sb, cind, ename, byte2Val.ToString()); break; case RageLib.GTA5.PSO.DataType.Enum: var enumInfo = cont.GetEnumInfo((MetaName)entry.ReferenceKey); switch (entry.Unk_5h) { default: ErrorXml(sb, cind, ename + ": Unexpected Enum subtype: " + entry.Unk_5h.ToString()); break; case 0: //int enum var intEVal = MetaUtils.SwapBytes(BitConverter.ToInt32(data, eoffset)); var intE = enumInfo.FindEntry(intEVal); StringTag(sb, cind, ename, HashString((MetaName)(intE?.EntryNameHash ?? 0))); break; case 2: //byte enum var byteEVal = data[eoffset]; var byteE = enumInfo.FindEntry(byteEVal); StringTag(sb, cind, ename, HashString((MetaName)(byteE?.EntryNameHash ?? 0))); break; } break; case RageLib.GTA5.PSO.DataType.Flags: uint fCount = ((uint)entry.ReferenceKey >> 16) & 0x0000FFFF; uint fEntry = ((uint)entry.ReferenceKey & 0xFFFF); var fEnt = structInfo.GetEntry((int)fEntry); PsoEnumInfo flagsInfo = null; if ((fEnt != null) && ((MetaName)fEnt.EntryNameHash == MetaName.ARRAYINFO)) { flagsInfo = cont.GetEnumInfo((MetaName)fEnt.ReferenceKey); } if (flagsInfo == null) { flagsInfo = cont.GetEnumInfo((MetaName)entry.EntryNameHash); } uint?flagsVal = null; switch (entry.Unk_5h) { default: ErrorXml(sb, cind, ename + ": Unexpected Flags subtype: " + entry.Unk_5h.ToString()); break; case 0: //int flags flagsVal = MetaUtils.SwapBytes(BitConverter.ToUInt32(data, eoffset)); break; case 1: //short flags flagsVal = MetaUtils.SwapBytes(BitConverter.ToUInt16(data, eoffset)); break; case 2: //byte flags flagsVal = data[eoffset]; break; } if (flagsVal.HasValue) { uint fv = flagsVal.Value; if (flagsInfo != null) { string fstr = ""; for (int n = 0; n < flagsInfo.EntriesCount; n++) { var fentry = flagsInfo.Entries[n]; var fmask = (1 << fentry.EntryKey); if ((fv & fmask) > 0) { if (fstr != "") { fstr += " "; } fstr += HashString((MetaName)fentry.EntryNameHash); } } StringTag(sb, cind, ename, fstr); } else { if (fv != 0) { ValueTag(sb, cind, ename, fv.ToString()); } else { SelfClosingTag(sb, cind, ename); } } } break; case RageLib.GTA5.PSO.DataType.Float: var floatVal = MetaUtils.SwapBytes(BitConverter.ToSingle(data, eoffset)); ValueTag(sb, cind, ename, FloatUtil.ToString(floatVal)); break; case RageLib.GTA5.PSO.DataType.Float2: var v2 = MetaUtils.SwapBytes(MetaUtils.ConvertData <Vector2>(data, eoffset)); SelfClosingTag(sb, cind, ename + " x=\"" + FloatUtil.ToString(v2.X) + "\" y=\"" + FloatUtil.ToString(v2.Y) + "\""); break; case RageLib.GTA5.PSO.DataType.Float3: var v3 = MetaUtils.SwapBytes(MetaUtils.ConvertData <Vector3>(data, eoffset)); SelfClosingTag(sb, cind, ename + " x=\"" + FloatUtil.ToString(v3.X) + "\" y=\"" + FloatUtil.ToString(v3.Y) + "\" z=\"" + FloatUtil.ToString(v3.Z) + "\""); break; case RageLib.GTA5.PSO.DataType.Float3a: //TODO: check this! var v3a = MetaUtils.SwapBytes(MetaUtils.ConvertData <Vector3>(data, eoffset)); SelfClosingTag(sb, cind, ename + " x=\"" + FloatUtil.ToString(v3a.X) + "\" y=\"" + FloatUtil.ToString(v3a.Y) + "\" z=\"" + FloatUtil.ToString(v3a.Z) + "\""); break; case RageLib.GTA5.PSO.DataType.Float4a: //TODO: check this! //...why are there 3 different types of float3? var v3b = MetaUtils.SwapBytes(MetaUtils.ConvertData <Vector3>(data, eoffset)); SelfClosingTag(sb, cind, ename + " x=\"" + FloatUtil.ToString(v3b.X) + "\" y=\"" + FloatUtil.ToString(v3b.Y) + "\" z=\"" + FloatUtil.ToString(v3b.Z) + "\""); break; case RageLib.GTA5.PSO.DataType.Float4: var v4 = MetaUtils.SwapBytes(MetaUtils.ConvertData <Vector4>(data, eoffset)); SelfClosingTag(sb, cind, ename + " x=\"" + FloatUtil.ToString(v4.X) + "\" y=\"" + FloatUtil.ToString(v4.Y) + "\" z=\"" + FloatUtil.ToString(v4.Z) + "\" w=\"" + FloatUtil.ToString(v4.W) + "\""); break; case RageLib.GTA5.PSO.DataType.SInt: //TODO: convert hashes? var int5Val = MetaUtils.SwapBytes(BitConverter.ToInt32(data, eoffset)); ValueTag(sb, cind, ename, int5Val.ToString()); break; case RageLib.GTA5.PSO.DataType.UInt: switch (entry.Unk_5h) { default: ErrorXml(sb, cind, ename + ": Unexpected Integer subtype: " + entry.Unk_5h.ToString()); break; case 0: //signed int var int6aVal = MetaUtils.SwapBytes(BitConverter.ToInt32(data, eoffset)); ValueTag(sb, cind, ename, int6aVal.ToString()); break; case 1: //unsigned int var int6bVal = MetaUtils.SwapBytes(BitConverter.ToUInt32(data, eoffset)); ValueTag(sb, cind, ename, "0x" + int6bVal.ToString("X").PadLeft(8, '0')); break; } break; case RageLib.GTA5.PSO.DataType.Long: var long2Val = MetaUtils.SwapBytes(BitConverter.ToUInt64(data, eoffset)); ValueTag(sb, cind, ename, long2Val.ToString()); break; case RageLib.GTA5.PSO.DataType.Map: WriteMapNode(sb, indent, cont, eoffset, entry, structInfo, ename); break; case RageLib.GTA5.PSO.DataType.SShort: var short3Val = (short)MetaUtils.SwapBytes(BitConverter.ToUInt16(data, eoffset)); ValueTag(sb, cind, ename, short3Val.ToString()); break; case RageLib.GTA5.PSO.DataType.UShort: var short4Val = MetaUtils.SwapBytes(BitConverter.ToUInt16(data, eoffset)); ValueTag(sb, cind, ename, short4Val.ToString()); break; case RageLib.GTA5.PSO.DataType.HFloat: //half float? var short1EVal = MetaUtils.SwapBytes(BitConverter.ToUInt16(data, eoffset)); ValueTag(sb, cind, ename, short1EVal.ToString()); break; case RageLib.GTA5.PSO.DataType.String: var str0 = GetStringValue(cont.Pso, entry, data, eoffset); if (str0 == null) { ErrorXml(sb, cind, ename + ": Unexpected String subtype: " + entry.Unk_5h.ToString()); } else { StringTag(sb, cind, ename, str0); } break; case RageLib.GTA5.PSO.DataType.Structure: switch (entry.Unk_5h) { default: ErrorXml(sb, cind, ename + ": Unexpected Structure subtype: " + entry.Unk_5h.ToString()); break; case 0: //default structure OpenTag(sb, cind, ename); WriteNode(sb, cind, cont, blockId, offset + entry.DataOffset, XmlTagMode.None, (MetaName)entry.ReferenceKey); CloseTag(sb, cind, ename); break; case 3: //structure pointer... case 4: //also pointer? what's the difference? var ptrVal = MetaUtils.ConvertData <PsoPOINTER>(data, eoffset); ptrVal.SwapEnd(); var pbid = ptrVal.BlockID; bool pbok = true; if (pbid <= 0) { pbok = false; //no block specified? } if (pbid > cont.Pso.DataMappingSection.EntriesCount) { pbok = false; //bad pointer? different type..? should output an error message here? } if (pbok) { WriteNode(sb, cind, cont, ptrVal.BlockID, (int)ptrVal.ItemOffset, XmlTagMode.None, (MetaName)entry.ReferenceKey); } else { SelfClosingTag(sb, cind, ename); } break; } break; } } switch (tagMode) { case XmlTagMode.Structure: CloseTag(sb, indent, name); break; case XmlTagMode.Item: case XmlTagMode.ItemAndType: CloseTag(sb, indent, "Item"); break; } }
private static void WriteArrayNode(StringBuilder sb, int indent, PsoCont cont, int blockId, int offset, PsoStructureEntryInfo entry, PsoStructureInfo estruct, string ename) { var block = cont.Pso.GetBlock(blockId); var boffset = offset + block.Offset; var eoffset = boffset + entry.DataOffset; var aOffset = offset + entry.DataOffset; var aBlockId = blockId; uint aCount = ((uint)entry.ReferenceKey >> 16) & 0x0000FFFF; var aind = indent + 1; string arrTag = ename; PsoStructureEntryInfo arrEntry = estruct.GetEntry((int)(entry.ReferenceKey & 0xFFFF)); if (arrEntry == null) { ErrorXml(sb, indent, "ARRAYINFO not found for " + ename + "!"); return; } var data = cont.Pso.DataSection.Data; switch (entry.Unk_5h) { default: ErrorXml(sb, indent, ename + ": WIP! Unsupported Array subtype: " + entry.Unk_5h.ToString()); break; case 0: //Array_Structure var arrStruc = MetaUtils.ConvertData <Array_Structure>(data, eoffset); arrStruc.SwapEnd(); aBlockId = (int)arrStruc.PointerDataId; aOffset = (int)arrStruc.PointerDataOffset; aCount = arrStruc.Count1; break; case 1: //Raw in-line array break; case 2: //also raw in-line array, but how different from above? break; case 4: //pointer array? default array? if (arrEntry.Unk_5h == 3) //pointers... { var arrStruc4 = MetaUtils.ConvertData <Array_Structure>(data, eoffset); arrStruc4.SwapEnd(); aBlockId = (int)arrStruc4.PointerDataId; aOffset = (int)arrStruc4.PointerDataOffset; aCount = arrStruc4.Count1; } break; case 129: //also raw inline array? in junctions.pso break; } switch (arrEntry.Type) { default: ErrorXml(sb, indent, ename + ": WIP! Unsupported array entry DataType: " + arrEntry.Type.ToString()); break; case RageLib.GTA5.PSO.DataType.Array: var rk0 = (entry.ReferenceKey >> 16) & 0x0000FFFF; if (rk0 > 0) { //var arrStruc5 = MetaUtils.ConvertDataArray<Array_StructurePointer>(data, eoffset, (int)rk0); //for (int n = 0; n < rk0; n++) arrStruc5[n].SwapEnd(); aOffset = offset + entry.DataOffset; OpenTag(sb, indent, arrTag); for (int n = 0; n < rk0; n++) //ARRAY ARRAY! { WriteArrayNode(sb, aind, cont, blockId, aOffset, arrEntry, estruct, "Item"); aOffset += 16; //ptr size... todo: what if not pointer array? } CloseTag(sb, indent, ename); } else { SelfClosingTag(sb, indent, arrTag); } break; case RageLib.GTA5.PSO.DataType.Structure: switch (arrEntry.Unk_5h) { case 0: break; case 3: //structure pointer array var arrStrucPtr = MetaUtils.ConvertData <Array_StructurePointer>(data, eoffset); arrStrucPtr.SwapEnd(); aBlockId = (int)arrStrucPtr.PointerDataId; aOffset = (int)arrStrucPtr.PointerDataOffset; aCount = arrStrucPtr.Count1; if (aCount > 0) { var ptrArr = PsoUtils.GetPointerArray(cont.Pso, arrStrucPtr); OpenTag(sb, indent, arrTag); for (int n = 0; n < aCount; n++) { var ptrVal = ptrArr[n]; WriteNode(sb, aind, cont, ptrVal.BlockID, (int)ptrVal.ItemOffset, XmlTagMode.ItemAndType); } CloseTag(sb, indent, ename); } break; default: break; } arrTag += " itemType=\"" + HashString((MetaName)arrEntry.ReferenceKey) + "\""; if (aCount > 0) { var aBlock = cont.Pso.GetBlock(aBlockId); var atyp = cont.GetStructureInfo((MetaName)arrEntry.ReferenceKey); if (aBlock == null) { ErrorXml(sb, indent, ename + ": Array block not found: " + aBlockId.ToString()); } else if ((MetaName)aBlock.NameHash != MetaName.PsoPOINTER) { OpenTag(sb, indent, arrTag); if (atyp == null) { ErrorXml(sb, indent, ename + ": Array type not found: " + HashString((MetaName)arrEntry.ReferenceKey)); } else { for (int n = 0; n < aCount; n++) { WriteNode(sb, aind, cont, aBlockId, aOffset, XmlTagMode.Item, (MetaName)arrEntry.ReferenceKey); aOffset += atyp.StructureLength; if ((n < (aCount - 1)) && (aBlock != null) && (aOffset >= aBlock.Length)) { break; } } } CloseTag(sb, indent, ename); } else { } //pointer array should get here, but it's already handled above. should improve this. } else { SelfClosingTag(sb, indent, arrTag); } break; case RageLib.GTA5.PSO.DataType.String: switch (entry.Unk_5h) { default: ErrorXml(sb, indent, ename + ": Unexpected String array subtype: " + entry.Unk_5h.ToString()); break; case 0: //hash array... var arrHash = MetaUtils.ConvertData <Array_uint>(data, eoffset); arrHash.SwapEnd(); var hashArr = PsoUtils.GetHashArray(cont.Pso, arrHash); WriteItemArray(sb, hashArr, indent, ename, "Hash", HashString); break; } break; case RageLib.GTA5.PSO.DataType.Float2: aCount = ((uint)entry.ReferenceKey >> 16) & 0x0000FFFF; arrTag += " itemType=\"Vector2\""; var v2Arr = MetaUtils.ConvertDataArray <Vector2>(data, eoffset, (int)aCount); WriteRawArray(sb, v2Arr, indent, ename, "Vector2", FormatVector2Swap, 1); break; case RageLib.GTA5.PSO.DataType.Float3: aCount = ((uint)entry.ReferenceKey >> 16) & 0x0000FFFF; arrTag += " itemType=\"Vector3\""; //this is actually aligned as vector4, the W values are crazy in places var v4Arr = MetaUtils.ConvertDataArray <Vector4>(data, eoffset, (int)aCount); WriteRawArray(sb, v4Arr, indent, ename, "Vector3", FormatVector4SwapXYZOnly, 1); break; case RageLib.GTA5.PSO.DataType.UByte: var barr = new byte[aCount]; if (aCount > 0) { var bblock = cont.Pso.GetBlock(aBlockId); var boffs = bblock.Offset + aOffset; Buffer.BlockCopy(data, boffs, barr, 0, (int)aCount); } WriteRawArray(sb, barr, indent, ename, "byte"); break; case RageLib.GTA5.PSO.DataType.Bool: var barr2 = new byte[aCount]; if (aCount > 0) { var bblock = cont.Pso.GetBlock(aBlockId); var boffs = bblock.Offset + aOffset; Buffer.BlockCopy(data, boffs, barr2, 0, (int)aCount); } WriteRawArray(sb, barr2, indent, ename, "boolean"); //todo: true/false output break; case RageLib.GTA5.PSO.DataType.Float: var arrFloat = MetaUtils.ConvertData <Array_float>(data, eoffset); arrFloat.SwapEnd(); var floatArr = PsoUtils.GetFloatArray(cont.Pso, arrFloat); WriteRawArray(sb, floatArr, indent, ename, "float"); break; case RageLib.GTA5.PSO.DataType.UShort: var arrShort = MetaUtils.ConvertData <Array_Structure>(data, eoffset); arrShort.SwapEnd(); var shortArr = PsoUtils.GetUShortArray(cont.Pso, arrShort); WriteRawArray(sb, shortArr, indent, ename, "ushort"); break; case RageLib.GTA5.PSO.DataType.UInt: var intArr = MetaUtils.ConvertDataArray <int>(data, eoffset, (int)aCount); WriteRawArray(sb, intArr, indent, ename, "int"); break; case RageLib.GTA5.PSO.DataType.SInt: var arrUint2 = MetaUtils.ConvertData <Array_uint>(data, eoffset); arrUint2.SwapEnd(); var intArr2 = PsoUtils.GetUintArray(cont.Pso, arrUint2); WriteRawArray(sb, intArr2, indent, ename, "int"); break; case RageLib.GTA5.PSO.DataType.Enum: var arrEnum = MetaUtils.ConvertData <Array_uint>(data, eoffset); arrEnum.SwapEnd(); var enumArr = PsoUtils.GetUintArray(cont.Pso, arrEnum); var enumDef = cont.GetEnumInfo((MetaName)arrEntry.ReferenceKey); WriteItemArray(sb, enumArr, indent, ename, "enum", (ie) => { var eval = enumDef?.FindEntry((int)ie); return(HashString((MetaName)(eval?.EntryNameHash ?? 0))); }); break; } }
static ModelData GenCol_GetModelData(ResourcePointerList64 <DrawableModel> models) { var vertices = new List <VertexVector3>(); var bbMin = new Vector3(float.MaxValue); var bbMax = new Vector3(float.MinValue); var bsCenter = Vector3.Zero; float bsRadius = 0.0f; var geometries = new List <GeometryData>(); for (int i = 0; i < models.Entries.Count; i++) { var entry = models.Entries[i]; for (int j = 0; j < entry.Geometries.Count; j++) { var geometry = entry.Geometries[j]; var gVertices = new List <VertexVector3>(); var gBbMin = new Vector3(float.MaxValue); var gBbMax = new Vector3(float.MinValue); var gBsCenter = Vector3.Zero; float gBsRadius = 0.0f; var vb = geometry.VertexData.VertexBytes; var vs = geometry.VertexData.VertexStride; var vc = geometry.VertexData.VertexCount; for (int k = 0; k < vc; k++) { var position = MetaUtils.ConvertData <Vector3>(vb, k * vs); var vertex = new VertexVector3(k, position); gBbMin = Vector3.Min(gBbMin, vertex.PositionVector); gBbMax = Vector3.Max(gBbMax, vertex.PositionVector); bbMin = Vector3.Min(bbMin, vertex.PositionVector); bbMax = Vector3.Max(bbMax, vertex.PositionVector); gVertices.Add(vertex); vertices.Add(vertex); } if (gVertices.Count > 0) { gBsCenter = (gBbMin + gBbMax) * 0.5f; foreach (var vertex in gVertices) { gBsRadius = Math.Max(gBsRadius, (vertex.PositionVector - gBsCenter).Length()); } } var gData = new GeometryData { Ref = geometry, BbMax = gBbMax, BbMin = gBbMin, BsCenter = gBsCenter, BsRadius = gBsRadius, Vertices = gVertices, Indices = geometry.IndexBuffer.Indices.Data.Select(e => e.Value).ToList() }; geometries.Add(gData); } } if (vertices.Count > 0) { bsCenter = (bbMin + bbMax) * 0.5f; foreach (var vertex in vertices) { bsRadius = Math.Max(bsRadius, (vertex.PositionVector - bsCenter).Length()); } } return(new ModelData { BbMin = bbMin, BbMax = bbMax, BsCenter = bsCenter, BsRadius = bsRadius, Geometries = geometries, Vertices = vertices }); }