Esempio n. 1
0
void UStructProperty::Serialize( FArchive& Ar )
{
	Super::Serialize( Ar );

	static UScriptStruct* FallbackStruct = GetFallbackStruct();
	
	if (Ar.IsPersistent() && Ar.GetLinker() && Ar.IsLoading() && !Struct)
	{
		// It's necessary to solve circular dependency problems, when serializing the Struct causes linking of the Property.
		Struct = FallbackStruct;
	}

	Ar << Struct;
#if WITH_EDITOR
	if (Ar.IsPersistent() && Ar.GetLinker())
	{
		if (!Struct && Ar.IsLoading())
		{
			UE_LOG(LogProperty, Error, TEXT("UStructProperty::Serialize Loading: Property '%s'. Unknown structure."), *GetFullName());
			Struct = FallbackStruct;
		}
		else if ((FallbackStruct == Struct) && Ar.IsSaving())
		{
			UE_LOG(LogProperty, Error, TEXT("UStructProperty::Serialize Saving: Property '%s'. FallbackStruct structure."), *GetFullName());
		}
	}
#endif // WITH_EDITOR
	if (Struct)
	{
		PreloadInnerStructMembers(this);
	}
	else
	{
		ensure(true);
	}
}
bool FStringAssetReference::Serialize(FArchive& Ar)
{
#if WITH_EDITOR
	if (Ar.IsSaving() && Ar.IsPersistent() && FCoreUObjectDelegates::StringAssetReferenceSaving.IsBound())
	{
		AssetLongPathname = FCoreUObjectDelegates::StringAssetReferenceSaving.Execute(AssetLongPathname);
	}
#endif // WITH_EDITOR
	Ar << *this;
#if WITH_EDITOR
	if (Ar.IsLoading() && Ar.IsPersistent() && FCoreUObjectDelegates::StringAssetReferenceLoaded.IsBound())
	{
		FCoreUObjectDelegates::StringAssetReferenceLoaded.Execute(AssetLongPathname);
	}
#endif // WITH_EDITOR

	if (Ar.IsLoading() && (Ar.GetPortFlags()&PPF_DuplicateForPIE))
	{
		// Remap unique ID if necessary
		FixupForPIE();
	}

	return true;
}
Esempio n. 3
0
void UStructProperty::SerializeItem( FArchive& Ar, void* Value, int32 MaxReadBytes, void const* Defaults ) const
{
	const bool bUseBinarySerialization = UseBinarySerialization(Ar);
	const bool bUseNativeSerialization = UseNativeSerialization();

	// Preload struct before serialization tracking to not double count time.
	if ( bUseBinarySerialization || bUseNativeSerialization)
	{
		Ar.Preload( Struct );
	}

	bool bItemSerialized = false;
	if (bUseNativeSerialization)
	{
		UScriptStruct::ICppStructOps* CppStructOps = Struct->GetCppStructOps();
		check(CppStructOps); // else should not have STRUCT_SerializeNative
		check(!Struct->InheritedCppStructOps()); // else should not have STRUCT_SerializeNative
		bItemSerialized = CppStructOps->Serialize(Ar, Value);
	}

	if (!bItemSerialized)
	{
		if( bUseBinarySerialization )
		{
			// Struct is already preloaded above.
			if ( !Ar.IsPersistent() && Ar.GetPortFlags() != 0 && !Struct->ShouldSerializeAtomically(Ar) )
			{
				Struct->SerializeBinEx( Ar, Value, Defaults, Struct );
			}
			else
			{
				Struct->SerializeBin( Ar, Value, MaxReadBytes );
			}
		}
		else
		{
			Struct->SerializeTaggedProperties( Ar, (uint8*)Value, Struct, (uint8*)Defaults );
		}
	}

	if (Struct->StructFlags & STRUCT_PostSerializeNative)
	{
		UScriptStruct::ICppStructOps* CppStructOps = Struct->GetCppStructOps();
		check(CppStructOps); // else should not have STRUCT_PostSerializeNative
		check(!Struct->InheritedCppStructOps()); // else should not have STRUCT_PostSerializeNative
		CppStructOps->PostSerialize(Ar, Value);
	}
}
// UObject interface.
void UTransBuffer::Serialize( FArchive& Ar )
{
	check( !Ar.IsPersistent() );

	CheckState();

	Super::Serialize( Ar );

	if ( IsObjectSerializationEnabled() || !Ar.IsObjectReferenceCollector() )
	{
		Ar << UndoBuffer;
	}
	Ar << ResetReason << UndoCount << ActiveCount << ActiveRecordCounts;

	CheckState();
}
void USoundWave::SerializeCookedPlatformData(FArchive& Ar)
{
	if (IsTemplate())
	{
		return;
	}

	DECLARE_SCOPE_CYCLE_COUNTER( TEXT("USoundWave::SerializeCookedPlatformData"), STAT_SoundWave_SerializeCookedPlatformData, STATGROUP_LoadTime );

#if WITH_EDITORONLY_DATA
	if (Ar.IsCooking() && Ar.IsPersistent())
	{
		check(!Ar.CookingTarget()->IsServerOnly());

		FName PlatformFormat = Ar.CookingTarget()->GetWaveFormat(this);
		FString DerivedDataKey;
		GetStreamedAudioDerivedDataKey(*this, PlatformFormat, DerivedDataKey);

		FStreamedAudioPlatformData *PlatformDataToSave = CookedPlatformData.FindRef(DerivedDataKey);

		if (PlatformDataToSave == NULL)
		{
			PlatformDataToSave = new FStreamedAudioPlatformData();
			PlatformDataToSave->Cache(*this, PlatformFormat, EStreamedAudioCacheFlags::InlineChunks | EStreamedAudioCacheFlags::Async);

			CookedPlatformData.Add(DerivedDataKey, PlatformDataToSave);
		}

		PlatformDataToSave->FinishCache();
		PlatformDataToSave->Serialize(Ar, this);
	}
	else
#endif // #if WITH_EDITORONLY_DATA
	{
		check(!FPlatformProperties::IsServerOnly());

		CleanupCachedRunningPlatformData();
		check(RunningPlatformData == NULL);

		// Don't serialize streaming data on servers, even if this platform supports streaming in theory
		RunningPlatformData = new FStreamedAudioPlatformData();
		RunningPlatformData->Serialize(Ar, this);
	}
}
void UAssetObjectProperty::SerializeItem( FArchive& Ar, void* Value, int32 MaxReadBytes, void const* Defaults ) const
{
	// We never serialize our reference while the garbage collector is harvesting references
	// to objects, because we don't want asset pointers to keep objects from being garbage collected
	// Allow persistent archives so they can keep track of string references. (e.g. FArchiveSaveTagImports)
	if( !Ar.IsObjectReferenceCollector() || Ar.IsModifyingWeakAndStrongReferences() || Ar.IsPersistent() )
	{
		FAssetPtr OldValue = *(FAssetPtr*)Value;
		Ar << *(FAssetPtr*)Value;

		if (Ar.IsLoading() || Ar.IsModifyingWeakAndStrongReferences()) 
		{
			if (OldValue.GetUniqueID() != ((FAssetPtr*)Value)->GetUniqueID())
			{
				CheckValidObject(Value);
			}
		}
	}
}
// UObject interface.
void UTransBuffer::Serialize( FArchive& Ar )
{
	check( !Ar.IsPersistent() );

	CheckState();

	// Handle garbage collection.
	Super::Serialize( Ar );

	// We cannot support undoing across GC if we allow it to eliminate references so we need
	// to suppress it.
	if ( IsObjectSerializationEnabled() || !Ar.IsObjectReferenceCollector() )
	{
		Ar.AllowEliminatingReferences( false );
		Ar << UndoBuffer;
		Ar.AllowEliminatingReferences( true );
	}
	Ar << ResetReason << UndoCount << ActiveCount;

	CheckState();
}
void UK2Node_VariableGet::Serialize(FArchive& Ar)
{
	// The following code is to attempt to log info related to UE-19729
	if (Ar.IsSaving() && Ar.IsPersistent())
	{
		uint32 PortFlagsToSkip = PPF_Duplicate | PPF_DuplicateForPIE;
		if (!(Ar.GetPortFlags() & PortFlagsToSkip))
		{
			if (UEdGraph* Graph = Cast<UEdGraph>(GetOuter()))
			{
				if (UBlueprint* Blueprint = FBlueprintEditorUtils::FindBlueprintForGraph(Graph))
				{
					if (!Blueprint->bBeingCompiled)
					{
						// The following line may spur the crash noted in UE-19729 and will confirm that the crash happens before the FiB gather.
						GetNodeTitle(ENodeTitleType::ListView);
					}
				}
			}
		}
	}
	Super::Serialize(Ar);
}
Esempio n. 9
0
/**
* Serialize function used to serialize this bulk data structure.
*
* @param Ar	Archive to serialize with
* @param Owner	Object owning the bulk data
* @param Idx	Index of bulk data item being serialized
*/
void FUntypedBulkData::Serialize( FArchive& Ar, UObject* Owner, int32 Idx )
{
	check( LockStatus == LOCKSTATUS_Unlocked );

	if(Ar.IsTransacting())
	{
		// Special case for transacting bulk data arrays.

		// constructing the object during load will save it to the transaction buffer. If it tries to load the bulk data now it will try to break it.
		bool bActuallySave = Ar.IsSaving() && (!Owner || !Owner->HasAnyFlags(RF_NeedLoad));

		Ar << bActuallySave;

		if (bActuallySave)
		{
			if(Ar.IsLoading())
			{
				// Flags for bulk data.
				Ar << BulkDataFlags;
				// Number of elements in array.
				Ar << ElementCount;

				// Allocate bulk data.
				check(bShouldFreeOnEmpty);
				BulkData = FMemory::Realloc( BulkData, GetBulkDataSize() );

				// Deserialize bulk data.
				SerializeBulkData( Ar, BulkData );
			}
			else if(Ar.IsSaving())
			{
				// Flags for bulk data.
				Ar << BulkDataFlags;
				// Number of elements in array.
				Ar << ElementCount;

				// Don't attempt to load or serialize BulkData if the current size is 0.
				// This could be a newly constructed BulkData that has not yet been loaded, 
				// and allocating 0 bytes now will cause a crash when we load.
				if (GetBulkDataSize() > 0)
				{
					// Make sure bulk data is loaded.
					MakeSureBulkDataIsLoaded();

					// Serialize bulk data.
					SerializeBulkData(Ar, BulkData);
				}
			}
		}
	}
	else if( Ar.IsPersistent() && !Ar.IsObjectReferenceCollector() && !Ar.ShouldSkipBulkData() )
	{
#if TRACK_BULKDATA_USE
		FThreadSafeBulkDataToObjectMap::Get().Add( this, Owner );
#endif
		// Offset where the bulkdata flags are stored
		int64 SavedBulkDataFlagsPos	= Ar.Tell();
		Ar << BulkDataFlags;

		// Number of elements in array.
		Ar << ElementCount;
		
		// We're loading from the persistent archive.
		if( Ar.IsLoading() )
		{
			Filename = TEXT("");
			
			// @todo when Landscape (and others?) only Lock/Unlock once, we can enable this
			if (false) // FPlatformProperties::RequiresCookedData())
			{
				// Bulk data that is being serialized via seekfree loading is single use only. This allows us 
				// to free the memory as e.g. the bulk data won't be attached to an archive in the case of
				// seek free loading.
				BulkDataFlags |= BULKDATA_SingleUse;
			}

			// Size on disk, which in the case of compression is != GetBulkDataSize()
			Ar << BulkDataSizeOnDisk;
			
			Ar << BulkDataOffsetInFile;

			// fix up the file offset 
			if (Owner != NULL && Owner->GetLinker())
			{
				BulkDataOffsetInFile += Owner->GetLinker()->Summary.BulkDataStartOffset;
			}

			// determine whether the payload is stored inline or at the end of the file
			bool bPayloadInline = !(BulkDataFlags&BULKDATA_PayloadAtEndOfFile);

// 			check( (bPayloadInline && BulkDataOffsetInFile == Ar.Tell()) || 
// 				   (!bPayloadInline && BulkDataOffsetInFile > Ar.Tell()));
			
			// We're allowing defered serialization.
			if( Ar.IsAllowingLazyLoading() && Owner != NULL)
			{
				Linker = Owner->GetLinker();

#if WITH_EDITOR
				check(Linker);
				Ar.AttachBulkData( Owner, this );
				AttachedAr = &Ar;
				
#else
				check(Linker.IsValid());
				Filename = Linker->Filename;
#endif // WITH_EDITOR
				// only skip over payload, if it's stored inline
				if (bPayloadInline)
				{
					Ar.Seek( Ar.Tell() + BulkDataSizeOnDisk );
				}
			}
			// Serialize the bulk data right away.
			else
			{
				// memory for bulk data can come from preallocated GPU-accessible resource memory or default to system memory
				BulkData = GetBulkDataResourceMemory(Owner,Idx);
				if( !BulkData )
				{
					BulkData = FMemory::Realloc( BulkData, GetBulkDataSize() );
				}
				
				if (bPayloadInline)
				{
					// if the payload is stored inline, just serialize it
					SerializeBulkData( Ar, BulkData );
				}
				else
				{
					// if the payload is NOT stored inline ...
					
					// store the current file offset
					int64 CurOffset = Ar.Tell();
					// seek to the location in the file where the payload is stored
					Ar.Seek(BulkDataOffsetInFile);
					// serialize the payload
					SerializeBulkData( Ar, BulkData );
					// seek to the location we came from
					Ar.Seek(CurOffset);
				}
			}
		}
		// We're saving to the persistent archive.
		else if( Ar.IsSaving() )
		{
			// check if we save the package compressed
			UPackage* Pkg = Owner ? dynamic_cast<UPackage*>(Owner->GetOutermost()) : nullptr;
			if (Pkg && !!(Pkg->PackageFlags & PKG_StoreCompressed) )
			{
				ECompressionFlags BaseCompressionMethod = COMPRESS_Default;
				if (Ar.IsCooking())
				{
					BaseCompressionMethod = Ar.CookingTarget()->GetBaseCompressionMethod();
				}

				StoreCompressedOnDisk(BaseCompressionMethod);
			}

			// Remove single element serialization requirement before saving out bulk data flags.
			BulkDataFlags &= ~BULKDATA_ForceSingleElementSerialization;

			// Make sure bulk data is loaded.
			MakeSureBulkDataIsLoaded();
			
			// Only serialize status information if wanted.
			int64 SavedBulkDataSizeOnDiskPos	= INDEX_NONE;
			int64 SavedBulkDataOffsetInFilePos	= INDEX_NONE;
			
			// Keep track of position we are going to serialize placeholder BulkDataSizeOnDisk.
			SavedBulkDataSizeOnDiskPos = Ar.Tell();
			BulkDataSizeOnDisk = INDEX_NONE;
			// And serialize the placeholder which is going to be overwritten later.
			Ar << BulkDataSizeOnDisk;

			// Keep track of position we are going to serialize placeholder BulkDataOffsetInFile.
			SavedBulkDataOffsetInFilePos = Ar.Tell();
			BulkDataOffsetInFile = INDEX_NONE;
			// And serialize the placeholder which is going to be overwritten later.
			Ar << BulkDataOffsetInFile;

				// try to get the linkersave object
			ULinkerSave* LinkerSave = dynamic_cast<ULinkerSave*>(Ar.GetLinker());

			// determine whether we are going to store the payload inline or not.
			bool bStoreInline = !!(BulkDataFlags&BULKDATA_ForceInlinePayload) || LinkerSave == NULL;

			if (!bStoreInline)
			{
				// set the flag indicating where the payload is stored
				BulkDataFlags |= BULKDATA_PayloadAtEndOfFile;

				// with no LinkerSave we have to store the data inline
				check(LinkerSave != NULL);				
				
				// add the bulkdata storage info object to the linkersave
				int32 Index = LinkerSave->BulkDataToAppend.AddZeroed(1);
				ULinkerSave::FBulkDataStorageInfo& BulkStore = LinkerSave->BulkDataToAppend[Index];

				BulkStore.BulkDataOffsetInFilePos = SavedBulkDataOffsetInFilePos;
				BulkStore.BulkDataSizeOnDiskPos = SavedBulkDataSizeOnDiskPos;
				BulkStore.BulkData = this;
				
				// Serialize bulk data into the storage info
				BulkDataSizeOnDisk = -1;
			}
			else
			{
				// set the flag indicating where the payload is stored
				BulkDataFlags &= ~BULKDATA_PayloadAtEndOfFile;

				int64 SavedBulkDataStartPos = Ar.Tell();

				// Serialize bulk data.
				SerializeBulkData( Ar, BulkData );
				// store the payload endpos
				int64 SavedBulkDataEndPos = Ar.Tell();

				checkf(SavedBulkDataStartPos >= 0 && SavedBulkDataEndPos >= 0,
					   TEXT("Bad archive positions for bulkdata. StartPos=%d EndPos=%d"),
					   SavedBulkDataStartPos, SavedBulkDataEndPos);

				BulkDataSizeOnDisk		= SavedBulkDataEndPos - SavedBulkDataStartPos;
				BulkDataOffsetInFile	= SavedBulkDataStartPos;
			}

			// store current file offset before seeking back
			int64 CurrentFileOffset = Ar.Tell();

			// Seek back and overwrite the flags 
			Ar.Seek(SavedBulkDataFlagsPos);
			Ar << BulkDataFlags;

			// Seek back and overwrite placeholder for BulkDataSizeOnDisk
			Ar.Seek( SavedBulkDataSizeOnDiskPos );
			Ar << BulkDataSizeOnDisk;

			// Seek back and overwrite placeholder for BulkDataOffsetInFile
			Ar.Seek( SavedBulkDataOffsetInFilePos );
			Ar << BulkDataOffsetInFile;

			// Seek to the end of written data so we don't clobber any data in subsequent write 
			// operations
			Ar.Seek(CurrentFileOffset);
		}
	}
}
Esempio n. 10
0
void FTextHistory_Base::SerializeForDisplayString(FArchive& Ar, FTextDisplayStringRef& InOutDisplayString)
{
	if(Ar.IsLoading())
	{
		// We will definitely need to do a rebuild later
		Revision = INDEX_NONE;

		FString Namespace;
		FString Key;
		FString SourceStringRaw;

		Ar << Namespace;
		Ar << Key;
		Ar << SourceStringRaw;

		// If there was a SourceString, store it in the member variable
		if(!SourceStringRaw.IsEmpty())
		{
			SourceString = MakeShareable(new FString(SourceStringRaw));
		}

		// Using the deserialized namespace and key, find the DisplayString.
		InOutDisplayString = FTextLocalizationManager::Get().GetDisplayString(Namespace, Key, SourceString.Get());
	}
	else if(Ar.IsSaving())
	{
		FString Namespace;
		FString Key;

		const bool FoundNamespaceAndKey = FTextLocalizationManager::Get().FindNamespaceAndKeyFromDisplayString(InOutDisplayString, Namespace, Key);

		// If this has no namespace or key, attempt to give it a GUID for a key and register it.
		if (!FoundNamespaceAndKey && GIsEditor && (Ar.IsPersistent() && !Ar.HasAnyPortFlags(PPF_Duplicate)))
		{
			Key = FGuid::NewGuid().ToString();
			if (!FTextLocalizationManager::Get().AddDisplayString(InOutDisplayString, Namespace, Key))
			{
				// Could not add display string, reset namespace and key.
				Namespace.Empty();
				Key.Empty();
			}
		}

		// Serialize the Namespace
		Ar << Namespace;

		// Serialize the Key
		Ar << Key;

		// Serialize the SourceString, or an empty string if there is none
		if( SourceString.IsValid() )
		{
			Ar << *(SourceString);
		}
		else
		{
			FString Empty;
			Ar << Empty;
		}
	}
}
Esempio n. 11
0
//------------------------------------------------------------------------------
bool FStructScriptLoader::LoadStructWithScript(UStruct* DestScriptContainer, FArchive& Ar, bool bAllowDeferredSerialization)
{
	if (!Ar.IsLoading() || !IsPrimed() || GIsDuplicatingClassForReinstancing)
	{
		return false;
	}

	bool const bIsLinkerLoader = Ar.IsPersistent() && (Ar.GetLinker() != nullptr);
	int32 const ScriptEndOffset = ScriptSerializationOffset + SerializedScriptSize;

	// to help us move development forward (and not have to support ancient 
	// script code), we define a minimum script version
	bool bSkipScriptSerialization = (Ar.UE4Ver() < VER_MIN_SCRIPTVM_UE4) || (Ar.LicenseeUE4Ver() < VER_MIN_SCRIPTVM_LICENSEEUE4);
#if WITH_EDITOR
	static const FBoolConfigValueHelper SkipByteCodeHelper(TEXT("StructSerialization"), TEXT("SkipByteCodeSerialization"));
	// in editor builds, we're going to regenerate the bytecode anyways, so it
	// is a waste of cycles to try and serialize it in
	bSkipScriptSerialization |= (bool)SkipByteCodeHelper;
#endif // WITH_EDITOR
	bSkipScriptSerialization &= bIsLinkerLoader; // to keep consistent with old UStruct::Serialize() functionality

	if (bSkipScriptSerialization)
	{
		int32 TrackedBufferSize = BytecodeBufferSize;
		BytecodeBufferSize = 0; // temporarily clear so that ClearScriptCode() doesn't leave Class->Script with anything allocated
		ClearScriptCode(DestScriptContainer);
		BytecodeBufferSize = TrackedBufferSize;

		// we have to at least move the archiver forward, so it is positioned 
		// where it expects to be (as if we read in the script)
		Ar.Seek(ScriptEndOffset);
		return false;
	}

	bAllowDeferredSerialization &= bIsLinkerLoader;
	if (bAllowDeferredSerialization && ShouldDeferScriptSerialization(Ar))
	{
		ULinkerLoad* Linker = CastChecked<ULinkerLoad>(Ar.GetLinker());
		FDeferredScriptTracker::Get().AddDeferredScriptObject(Linker, DestScriptContainer, *this);

		// we have to at least move the archiver forward, so it is positioned 
		// where it expects to be (as if we read in the script)
		Ar.Seek(ScriptEndOffset);
		return false;
	}

	Ar.Seek(ScriptSerializationOffset);
	if (bIsLinkerLoader)
	{
		ULinkerLoad* LinkerLoad = CastChecked<ULinkerLoad>(Ar.GetLinker());

		TArray<uint8> ShaScriptBuffer;
		ShaScriptBuffer.AddUninitialized(SerializedScriptSize);

		Ar.Serialize(ShaScriptBuffer.GetData(), SerializedScriptSize);
		ensure(ScriptEndOffset == Ar.Tell());
		LinkerLoad->UpdateScriptSHAKey(ShaScriptBuffer);

		Ar.Seek(ScriptSerializationOffset);
	}

	DestScriptContainer->Script.Empty(BytecodeBufferSize);
	DestScriptContainer->Script.AddUninitialized(BytecodeBufferSize);

	int32 BytecodeIndex = 0;
	while (BytecodeIndex < BytecodeBufferSize)
	{
		DestScriptContainer->SerializeExpr(BytecodeIndex, Ar);
	}
	ensure(ScriptEndOffset == Ar.Tell());
	checkf(BytecodeIndex == BytecodeBufferSize, TEXT("'%s' script expression-count mismatch; Expected: %i, Got: %i"), *DestScriptContainer->GetName(), BytecodeBufferSize, BytecodeIndex);

	if (!GUObjectArray.IsDisregardForGC(DestScriptContainer))
	{
		DestScriptContainer->ScriptObjectReferences.Empty();
		FArchiveScriptReferenceCollector ObjRefCollector(DestScriptContainer->ScriptObjectReferences);

		BytecodeIndex = 0;
		while (BytecodeIndex < BytecodeBufferSize)
		{
			DestScriptContainer->SerializeExpr(BytecodeIndex, ObjRefCollector);
		}
	}

	// success! (we filled the target with serialized script code)
	return true;
}