EM_Task/CoreUObject/Private/Serialization/ArchiveUObjectFromStructuredArchive.cpp

213 lines
6.4 KiB
C++
Raw Normal View History

2026-02-13 16:18:33 +08:00
// Copyright Epic Games, Inc. All Rights Reserved.
#include "Serialization/ArchiveUObjectFromStructuredArchive.h"
#include "UObject/LinkerSave.h"
#include "Interfaces/ITargetPlatform.h"
#if WITH_TEXT_ARCHIVE_SUPPORT
FArchiveUObjectFromStructuredArchiveImpl::FArchiveUObjectFromStructuredArchiveImpl(FStructuredArchive::FSlot Slot)
: Super(Slot)
{
}
FArchive& FArchiveUObjectFromStructuredArchiveImpl::operator<<(FLazyObjectPtr& Value)
{
OpenArchive();
if (InnerArchive.IsTextFormat())
{
if (IsLoading())
{
int32 ObjectIdx = 0;
Serialize(&ObjectIdx, sizeof(ObjectIdx));
Value = LazyObjectPtrs[ObjectIdx];
}
else
{
int32* IdxPtr = LazyObjectPtrToIndex.Find(Value);
if (IdxPtr == nullptr)
{
IdxPtr = &(LazyObjectPtrToIndex.Add(Value));
*IdxPtr = LazyObjectPtrs.Add(Value);
}
Serialize(IdxPtr, sizeof(*IdxPtr));
}
}
else
{
InnerArchive << Value;
}
return *this;
}
FArchive& FArchiveUObjectFromStructuredArchiveImpl::operator<<(FSoftObjectPtr& Value)
{
OpenArchive();
if (InnerArchive.IsTextFormat())
{
if (IsLoading())
{
int32 ObjectIdx = 0;
Serialize(&ObjectIdx, sizeof(ObjectIdx));
Value = SoftObjectPtrs[ObjectIdx];
}
else
{
int32* IdxPtr = SoftObjectPtrToIndex.Find(Value);
if (IdxPtr == nullptr)
{
IdxPtr = &(SoftObjectPtrToIndex.Add(Value));
*IdxPtr = SoftObjectPtrs.Add(Value);
}
Serialize(IdxPtr, sizeof(*IdxPtr));
}
}
else
{
InnerArchive << Value;
}
return *this;
}
FArchive& FArchiveUObjectFromStructuredArchiveImpl::operator<<(FSoftObjectPath& Value)
{
OpenArchive();
if (InnerArchive.IsTextFormat())
{
if (IsLoading())
{
int32 ObjectIdx = 0;
Serialize(&ObjectIdx, sizeof(ObjectIdx));
Value = SoftObjectPaths[ObjectIdx];
}
else
{
int32* IdxPtr = SoftObjectPathToIndex.Find(Value);
if (IdxPtr == nullptr)
{
IdxPtr = &(SoftObjectPathToIndex.Add(Value));
*IdxPtr = SoftObjectPaths.Add(Value);
}
#if 1
// Temp workaround for emulating the behaviour of soft asset path serialization. Use these thread specific overrides to determine if we should actually save
// a reference to the path. If not, we still record the path in our list so that we get the correct behaviour later on when we pass these references down to the underlying
// archive
FName PackageName, PropertyName;
ESoftObjectPathCollectType CollectType = ESoftObjectPathCollectType::AlwaysCollect;
ESoftObjectPathSerializeType SerializeType = ESoftObjectPathSerializeType::AlwaysSerialize;
FSoftObjectPathThreadContext& ThreadContext = FSoftObjectPathThreadContext::Get();
ThreadContext.GetSerializationOptions(PackageName, PropertyName, CollectType, SerializeType, this);
if (SerializeType == ESoftObjectPathSerializeType::AlwaysSerialize)
{
Serialize(IdxPtr, sizeof(*IdxPtr));
}
#else
Serialize(IdxPtr, sizeof(*IdxPtr));
#endif
}
}
else
{
InnerArchive << Value;
}
return *this;
}
FArchive& FArchiveUObjectFromStructuredArchiveImpl::operator<<(FWeakObjectPtr& Value)
{
OpenArchive();
if (InnerArchive.IsTextFormat())
{
if (IsLoading())
{
int32 ObjectIdx = 0;
Serialize(&ObjectIdx, sizeof(ObjectIdx));
Value = WeakObjectPtrs[ObjectIdx];
}
else
{
int32* IdxPtr = WeakObjectPtrToIndex.Find(Value);
if (IdxPtr == nullptr)
{
IdxPtr = &(WeakObjectPtrToIndex.Add(Value));
*IdxPtr = WeakObjectPtrs.Add(Value);
}
Serialize(IdxPtr, sizeof(*IdxPtr));
}
}
else
{
InnerArchive << Value;
}
return *this;
}
void FArchiveUObjectFromStructuredArchiveImpl::PushFileRegionType(EFileRegionType Type)
{
check(CurrentFileRegionType == EFileRegionType::None);
check(Type != EFileRegionType::None);
CurrentFileRegionType = Type;
FileRegionStart = Tell();
}
void FArchiveUObjectFromStructuredArchiveImpl::PopFileRegionType()
{
check(CurrentFileRegionType != EFileRegionType::None);
if (IsCooking() && CookingTarget()->SupportsFeature(ETargetPlatformFeatures::CookFileRegionMetadata))
{
FLinkerSave* LinkerSave = Cast<FLinkerSave>(GetLinker());
check(LinkerSave);
int64 Length = Tell() - FileRegionStart;
if (Length > 0)
{
LinkerSave->FileRegions.Add(FFileRegion(FileRegionStart, Length, CurrentFileRegionType));
}
}
CurrentFileRegionType = EFileRegionType::None;
}
bool FArchiveUObjectFromStructuredArchiveImpl::Finalize(FStructuredArchive::FRecord Record)
{
check(CurrentFileRegionType == EFileRegionType::None);
bool bShouldSerialize = Super::Finalize(Record);
if (bShouldSerialize)
{
TOptional<FStructuredArchive::FSlot> LazyObjectPtrsSlot = Record.TryEnterField(SA_FIELD_NAME(TEXT("LazyObjectPtrs")), LazyObjectPtrs.Num() > 0);
if (LazyObjectPtrsSlot.IsSet())
{
LazyObjectPtrsSlot.GetValue() << LazyObjectPtrs;
}
TOptional<FStructuredArchive::FSlot> SoftObjectPtrsSlot = Record.TryEnterField(SA_FIELD_NAME(TEXT("SoftObjectPtrs")), SoftObjectPtrs.Num() > 0);
if (SoftObjectPtrsSlot.IsSet())
{
SoftObjectPtrsSlot.GetValue() << SoftObjectPtrs;
}
TOptional<FStructuredArchive::FSlot> SoftObjectPathsSlot = Record.TryEnterField(SA_FIELD_NAME(TEXT("SoftObjectPaths")), SoftObjectPaths.Num() > 0);
if (SoftObjectPathsSlot.IsSet())
{
SoftObjectPathsSlot.GetValue() << SoftObjectPaths;
}
TOptional<FStructuredArchive::FSlot> WeakObjectPtrsSlot = Record.TryEnterField(SA_FIELD_NAME(TEXT("WeakObjectPtrs")), WeakObjectPtrs.Num() > 0);
if (WeakObjectPtrsSlot.IsSet())
{
WeakObjectPtrsSlot.GetValue() << WeakObjectPtrs;
}
}
return bShouldSerialize;
}
#endif