private void SerializeCompressedData(FAssetArchive Ar) { // These fields were serialized as properties in pre-UE4.12 engine version KeyEncodingFormat = Ar.Read <AnimationKeyFormat>(); TranslationCompressionFormat = Ar.Read <AnimationCompressionFormat>(); RotationCompressionFormat = Ar.Read <AnimationCompressionFormat>(); ScaleCompressionFormat = Ar.Read <AnimationCompressionFormat>(); CompressedTrackOffsets = Ar.ReadArray <int>(); CompressedScaleOffsets = new FCompressedOffsetData(Ar); if (Ar.Game >= EGame.GAME_UE4_21) { // UE4.21+ - added compressed segments; disappeared in 4.23 CompressedSegments = Ar.ReadArray <FCompressedSegment>(); if (CompressedSegments.Length > 0) { Log.Information("animation has CompressedSegments!"); } } CompressedTrackToSkeletonMapTable = Ar.ReadArray <FTrackToSkeletonMap>(); if (Ar.Game < EGame.GAME_UE4_22) { CompressedCurveData = new FStructFallback(Ar, "RawCurveTracks"); } else { var compressedCurveNames = Ar.ReadArray(() => new FSmartName(Ar)); } if (Ar.Game >= EGame.GAME_UE4_17) { // UE4.17+ var compressedRawDataSize = Ar.Read <int>(); } if (Ar.Game >= EGame.GAME_UE4_22) { var compressedNumFrames = Ar.Read <int>(); } // compressed data var numBytes = Ar.Read <int>(); CompressedByteStream = Ar.ReadBytes(numBytes); if (Ar.Game >= EGame.GAME_UE4_22) { var curveCodecPath = Ar.ReadFString(); var compressedCurveByteStream = Ar.ReadArray <byte>(); } // Fix layout of "byte swapped" data (workaround for UE4 bug) if (KeyEncodingFormat == AnimationKeyFormat.AKF_PerTrackCompression && CompressedScaleOffsets.OffsetData.Length > 0 && Ar.Game < EGame.GAME_UE4_23) { throw new NotImplementedException(); } }
// UE4.23-4.24 has changed compressed data layout for streaming, so it's worth making a separate // serializer function for it. private void SerializeCompressedData2(FAssetArchive Ar) { var compressedRawDataSize = Ar.Read <int>(); CompressedTrackToSkeletonMapTable = Ar.ReadArray <FTrackToSkeletonMap>(); var compressedCurveNames = Ar.ReadArray(() => new FSmartName(Ar)); // Since 4.23, this is FUECompressedAnimData::SerializeCompressedData KeyEncodingFormat = Ar.Read <AnimationKeyFormat>(); TranslationCompressionFormat = Ar.Read <AnimationCompressionFormat>(); RotationCompressionFormat = Ar.Read <AnimationCompressionFormat>(); ScaleCompressionFormat = Ar.Read <AnimationCompressionFormat>(); var compressedNumFrames = Ar.Read <int>(); // SerializeView() just serializes array size var compressedTrackOffsetsNum = Ar.Read <int>(); var compressedScaleOffsetsNum = Ar.Read <int>(); CompressedScaleOffsets = new FCompressedOffsetData(Ar.Read <int>()); var compressedByteStreamNum = Ar.Read <int>(); // ... end of FUECompressedAnimData::SerializeCompressedData var numBytes = Ar.Read <int>(); var bUseBulkDataForLoad = Ar.ReadBoolean(); // In UE4.23 CompressedByteStream field exists in FUECompressedAnimData (as TArrayView) and in // FCompressedAnimSequence (as byte array). Serialization is done in FCompressedAnimSequence, // either as TArray or as bulk, and then array is separated onto multiple "views" for // FUECompressedAnimData. We'll use a different name for "joined" serialized array here to // avoid confuse. byte[] serializedByteStream; if (bUseBulkDataForLoad) { throw new NotImplementedException("Anim: bUseBulkDataForLoad not implemented"); //todo: read from bulk to serializedByteStream } else { serializedByteStream = Ar.ReadBytes(numBytes); } // Setup all array views from single array. In UE4 this is done in FUECompressedAnimData::InitViewsFromBuffer. // We'll simply copy array data away from SerializedByteStream, and then SerializedByteStream // will be released from memory as it is a local variable here. // Note: copying is not byte-order wise, so if there will be any problems in the future, // should use byte swap functions. using (var tempAr = new FByteArchive("SerializedByteStream", serializedByteStream, Ar.Versions)) { CompressedTrackOffsets = tempAr.ReadArray <int>(compressedTrackOffsetsNum); CompressedScaleOffsets.OffsetData = tempAr.ReadArray <int>(compressedScaleOffsetsNum); CompressedByteStream = tempAr.ReadBytes(compressedByteStreamNum); } var curveCodecPath = Ar.ReadFString(); var compressedCurveByteStream = Ar.ReadArray <byte>(); }