115 lines
3.8 KiB
C++
115 lines
3.8 KiB
C++
|
|
// Copyright Epic Games, Inc. All Rights Reserved.
|
||
|
|
|
||
|
|
#include "Serialization/ArchiveObjectCrc32.h"
|
||
|
|
#include "UObject/Object.h"
|
||
|
|
|
||
|
|
DEFINE_LOG_CATEGORY_STATIC(LogArchiveObjectCrc32, Log, All);
|
||
|
|
|
||
|
|
// #define DEBUG_ARCHIVE_OBJECT_CRC32
|
||
|
|
|
||
|
|
/*----------------------------------------------------------------------------
|
||
|
|
FArchiveObjectCrc32
|
||
|
|
----------------------------------------------------------------------------*/
|
||
|
|
|
||
|
|
FArchiveObjectCrc32::FArchiveObjectCrc32()
|
||
|
|
: MemoryWriter(SerializedObjectData), ObjectBeingSerialized(NULL), RootObject(NULL)
|
||
|
|
{
|
||
|
|
ArIgnoreOuterRef = true;
|
||
|
|
|
||
|
|
// Set FArchiveObjectCrc32 to be a saving archive instead of a reference collector.
|
||
|
|
// Reference collection causes FSoftObjectPtrs to be serialized by their weak pointer,
|
||
|
|
// which doesn't give a stable CRC. Serializing these to a saving archive will
|
||
|
|
// use a string reference instead, which is a more meaningful CRC'able state.
|
||
|
|
SetIsSaving(true);
|
||
|
|
}
|
||
|
|
|
||
|
|
void FArchiveObjectCrc32::Serialize(void* Data, int64 Length)
|
||
|
|
{
|
||
|
|
MemoryWriter.Serialize(Data, Length);
|
||
|
|
}
|
||
|
|
|
||
|
|
FArchive& FArchiveObjectCrc32::operator<<(class FName& Name)
|
||
|
|
{
|
||
|
|
checkSlow(ObjectBeingSerialized);
|
||
|
|
|
||
|
|
// Don't include the name of the object being serialized, since that isn't technically part of the object's state
|
||
|
|
if (Name != ObjectBeingSerialized->GetFName())
|
||
|
|
{
|
||
|
|
MemoryWriter << Name;
|
||
|
|
}
|
||
|
|
|
||
|
|
return *this;
|
||
|
|
}
|
||
|
|
|
||
|
|
FArchive& FArchiveObjectCrc32::operator<<(class UObject*& Object)
|
||
|
|
{
|
||
|
|
FArchive& Ar = *this;
|
||
|
|
|
||
|
|
if (!Object || !Object->IsIn(RootObject))
|
||
|
|
{
|
||
|
|
auto UniqueName = GetPathNameSafe(Object);
|
||
|
|
Ar << UniqueName;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
ObjectsToSerialize.Enqueue(Object);
|
||
|
|
}
|
||
|
|
|
||
|
|
return Ar;
|
||
|
|
}
|
||
|
|
|
||
|
|
uint32 FArchiveObjectCrc32::Crc32(UObject* Object, uint32 CRC)
|
||
|
|
{
|
||
|
|
#ifdef DEBUG_ARCHIVE_OBJECT_CRC32
|
||
|
|
const double StartTime = FPlatformTime::Seconds();
|
||
|
|
UE_LOG(LogArchiveObjectCrc32, Log, TEXT("### Calculating CRC for object: %s with outer: %s"), *Object->GetName(), Object->GetOuter() ? *Object->GetOuter()->GetName() : TEXT("NULL"));
|
||
|
|
#endif
|
||
|
|
RootObject = Object;
|
||
|
|
if (Object)
|
||
|
|
{
|
||
|
|
TSet<UObject*> SerializedObjects;
|
||
|
|
|
||
|
|
// Start with the given object
|
||
|
|
ObjectsToSerialize.Enqueue(Object);
|
||
|
|
|
||
|
|
// Continue until we no longer have any objects to serialized
|
||
|
|
while (ObjectsToSerialize.Dequeue(Object))
|
||
|
|
{
|
||
|
|
bool bAlreadyProcessed = false;
|
||
|
|
SerializedObjects.Add(Object, &bAlreadyProcessed);
|
||
|
|
// If we haven't already serialized this object
|
||
|
|
if (!bAlreadyProcessed)
|
||
|
|
{
|
||
|
|
#ifdef DEBUG_ARCHIVE_OBJECT_CRC32
|
||
|
|
UE_LOG(LogArchiveObjectCrc32, Log, TEXT("- Serializing object: %s with outer: %s"), *Object->GetName(), Object->GetOuter() ? *Object->GetOuter()->GetName() : TEXT("NULL"));
|
||
|
|
#endif
|
||
|
|
// Serialize it
|
||
|
|
ObjectBeingSerialized = Object;
|
||
|
|
if (!CustomSerialize(Object))
|
||
|
|
{
|
||
|
|
Object->Serialize(*this);
|
||
|
|
}
|
||
|
|
ObjectBeingSerialized = NULL;
|
||
|
|
|
||
|
|
// Calculate the CRC, compounding it with the checksum calculated from the previous object
|
||
|
|
CRC = FCrc::MemCrc32(SerializedObjectData.GetData(), SerializedObjectData.Num(), CRC);
|
||
|
|
#ifdef DEBUG_ARCHIVE_OBJECT_CRC32
|
||
|
|
UE_LOG(LogArchiveObjectCrc32, Log, TEXT("=> object: '%s', total size: %d bytes, checksum: 0x%08x"), *GetPathNameSafe(Object), SerializedObjectData.Num(), CRC);
|
||
|
|
#endif
|
||
|
|
// Cleanup
|
||
|
|
MemoryWriter.Seek(0L);
|
||
|
|
SerializedObjectData.Empty();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Cleanup
|
||
|
|
SerializedObjects.Empty();
|
||
|
|
RootObject = NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
#ifdef DEBUG_ARCHIVE_OBJECT_CRC32
|
||
|
|
UE_LOG(LogArchiveObjectCrc32, Log, TEXT("### Finished (%.02f ms), final checksum: 0x%08x"), (FPlatformTime::Seconds() - StartTime) * 1000.0f, CRC);
|
||
|
|
#endif
|
||
|
|
return CRC;
|
||
|
|
}
|