UNPKG

unreal.js

Version:

A pak reader for games like VALORANT & Fortnite written in Node.JS

157 lines (156 loc) 8.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.UStaticMesh = void 0; const UStaticMesh_Properties_1 = require("./UStaticMesh_Properties"); const FStripDataFlags_1 = require("../../objects/engine/FStripDataFlags"); const Guid_1 = require("../../objects/core/misc/Guid"); const FVector_1 = require("../../objects/core/math/FVector"); const FBoxSphereBounds_1 = require("../../objects/core/math/FBoxSphereBounds"); const UnrealArray_1 = require("../../../util/UnrealArray"); const FStaticMaterial_1 = require("../objects/meshes/FStaticMaterial"); const Versions_1 = require("../../versions/Versions"); const Exceptions_1 = require("../../../exceptions/Exceptions"); const index_1 = require("../../../index"); const FRenderingObjectVersion_1 = require("../../versions/FRenderingObjectVersion"); const FStaticMeshLODResources_1 = require("../objects/meshes/FStaticMeshLODResources"); const FDistanceFieldVolumeData_1 = require("../../objects/engine/FDistanceFieldVolumeData"); const FEditorObjectVersion_1 = require("../../versions/FEditorObjectVersion"); class UStaticMesh extends UStaticMesh_Properties_1.UStaticMesh_Properties { constructor() { super(...arguments); this.stripFlags = null; this.bodySetup = null; this.navCollision = null; // UNavCollision this.lightingGuid = null; this.sockets = null; this.lods = new Array(); this.bounds = new FBoxSphereBounds_1.FBoxSphereBounds(new FVector_1.FVector(), new FVector_1.FVector(), 0); this.lodsShareStaticLighting = false; this.screenSize = new UnrealArray_1.UnrealArray(8, () => 0); this.staticMaterials = Array(); this.materials = new Array(); } deserialize(Ar, validPos) { super.deserialize(Ar, validPos); this.stripFlags = new FStripDataFlags_1.FStripDataFlags(Ar); const cooked = Ar.readBoolean(); this.bodySetup = Ar.readObject(); this.navCollision = Ar.ver >= Versions_1.VER_UE4_STATIC_MESH_STORE_NAV_COLLISION ? Ar.readObject() : null; if (!this.stripFlags.isEditorDataStripped) { } this.lightingGuid = new Guid_1.FGuid(Ar); const socketLength = Ar.readInt32(); this.sockets = new Array(socketLength); for (let i = 0; i < socketLength; ++i) { this.sockets[i] = Ar.readObject(); } if (!this.stripFlags.isEditorDataStripped) // TODO https://github.com/gildor2/UEViewer/blob/master/Unreal/UnMesh4.cpp#L2382 throw new Exceptions_1.ParserException("Static Mesh with Editor Data not implemented yet"); // this if block doesn't always make sense to me: // https://github.com/FabianFG/JFortniteParse/blob/85c07b3d8b4e89e8d5a97a55ba621ee2ec9a459b/src/main/kotlin/me/fungames/jfortniteparse/ue4/assets/exports/UStaticMesh.kt#L64 // within the if block which is used if cooked == true there are multiple extra checks of the cooked variable // even tho it is never reassigned and it is marked as non changeable ('val') // i guess this is an issue so therefore im skipping some checks // serialize FStaticMeshRenderData if (cooked) { if (Ar.versions.get("StaticMesh.KeepMobileMinLODSettingOnDesktop")) { // The serialization of this variable is cvar-dependent in UE4, so there's no clear way to understand // if it should be serialize in our code or not. Ar.readInt32(); // MinMobileLODIdx } /*if (!cooked) { ^ read above Ar.readTArray { Ar.readInt32() } // WedgeMap Ar.readTArray { Ar.readInt32() } // MaterialIndexToImportIndex }*/ const lodsLength = Ar.readInt32(); this.lods = new Array(lodsLength); for (let i = 0; i < lodsLength; ++i) { this.lods[i] = new FStaticMeshLODResources_1.FStaticMeshLODResources(Ar); } if (Ar.game >= index_1.Game.GAME_UE4(23)) Ar.readUInt8(); // NumInlinedLODs // {...} ^ read above if (Ar.ver >= Versions_1.VER_UE4_RENAME_CROUCHMOVESCHARACTERDOWN) { let stripped = false; if (Ar.ver >= Versions_1.VER_UE4_RENAME_WIDGET_VISIBILITY) { const stripFlags2 = new FStripDataFlags_1.FStripDataFlags(Ar); stripped = stripFlags2.isDataStrippedForServer; if (Ar.game >= index_1.Game.GAME_UE4(21)) { // 4.21 uses additional strip flag for distance field stripped = Boolean(Number(stripped) | Number(stripFlags2.isClassDataStripped(1))); } } if (!stripped) { // serialize FDistanceFieldVolumeData for each LOD for (let i = 0; i < lodsLength; ++i) { const hasDistanceDataField = Ar.readBoolean(); if (hasDistanceDataField) new FDistanceFieldVolumeData_1.FDistanceFieldVolumeData(Ar); // VolumeData } } } this.bounds = new FBoxSphereBounds_1.FBoxSphereBounds(Ar); // Note: bLODsShareStaticLighting field exists in all engine versions except UE4.15. if (Ar.versions.get("StaticMesh.HasLODsShareStaticLighting")) this.lodsShareStaticLighting = Ar.readBoolean(); if (Ar.game < index_1.Game.GAME_UE4(14)) Ar.readBoolean(); // bReducedBySimplygon if (FRenderingObjectVersion_1.FRenderingObjectVersion.get(Ar) < FRenderingObjectVersion_1.EFRenderingObjectVersion.TextureStreamingMeshUVChannelData) { // StreamingTextureFactors // StreamingTextureFactor for each UV set for (let i = 0; i < UStaticMesh.MAX_STATIC_UV_SETS_UE4; ++i) Ar.readFloat32(); Ar.readFloat32(); // MaxStreamingTextureFactor } // {...} ^ read above // ScreenSize for each LOD const maxNumLods = Ar.game >= index_1.Game.GAME_UE4(9) ? UStaticMesh.MAX_STATIC_LODS_UE4 : 4; for (let i = 0; i < maxNumLods; ++i) { if (Ar.game >= index_1.Game.GAME_UE4(20)) Ar.readBoolean(); // bFloatCooked this.screenSize[i] = Ar.readFloat32(); } } // end of FStaticMeshRenderData if (cooked && Ar.game >= index_1.Game.GAME_UE4(20)) { const hasOccluderData = Ar.readBoolean(); if (hasOccluderData) { const _length1 = Ar.readInt32(); for (let i = 0; i < _length1; ++i) new FVector_1.FVector(Ar); // Vertices const _length2 = Ar.readInt32(); for (let i = 0; i < _length2; ++i) Ar.readUInt16(); // Indices } } if (Ar.game >= index_1.Game.GAME_UE4(14)) { // Serialize following data to obtain material references for UE4.14+. // Don't bother serializing anything beyond this point in earlier versions. // Note: really, UE4 uses VER_UE4_SPEEDTREE_STATICMESH const hasSpeedTreeWind = Ar.readBoolean(); if (hasSpeedTreeWind) { // TODO - FSpeedTreeWind serialization // Ignore remaining data } else { if (FEditorObjectVersion_1.FEditorObjectVersion.get(Ar) >= FEditorObjectVersion_1.EFEditorObjectVersion.RefactorMeshEditorMaterials) { // UE4.14+ - "Materials" are deprecated, added StaticMaterials const staticMaterialsLength = Ar.readInt32(); this.staticMaterials = new Array(staticMaterialsLength); for (let i = 0; i < staticMaterialsLength; ++i) this.staticMaterials[i] = new FStaticMaterial_1.FStaticMaterial(Ar); } } } this.materials = this.staticMaterials.map(it => it.materialInterface).filter(it => it != null); // Drop remaining SpeedTree data if (validPos > 0) Ar.pos = validPos; } serialize(Ar) { throw new Exceptions_1.ParserException("Serializing UStaticMesh not supported"); } } exports.UStaticMesh = UStaticMesh; UStaticMesh.MAX_STATIC_UV_SETS_UE4 = 8; UStaticMesh.MAX_STATIC_LODS_UE4 = 8;