void FLazyObjectPtr::PossiblySerializeObjectGuid(UObject *Object, FArchive& Ar)
{
	if (Ar.IsSaving() || Ar.IsCountingMemory())
	{
		FUniqueObjectGuid Guid = GuidAnnotation.GetAnnotation(Object);
		bool HasGuid = Guid.IsValid();
		Ar << HasGuid;
		if (HasGuid)
		{
			if (Ar.GetPortFlags() & PPF_DuplicateForPIE)
			{
				check(GPlayInEditorID != -1);
				FGuid &FoundGuid = PIEGuidMap[GPlayInEditorID % MAX_PIE_INSTANCES].FindOrAdd(Guid.GetGuid());
				if (!FoundGuid.IsValid())
				{
					Guid = FoundGuid = FGuid::NewGuid();
				}
				else
				{
					Guid = FoundGuid;
				}
			}

			Ar << Guid;
		}
	}
	else if (Ar.IsLoading())
	{
		bool HasGuid = false;
		Ar << HasGuid;
		if (HasGuid)
		{
			FUniqueObjectGuid Guid;
			Ar << Guid;

			// Don't try and resolve GUIDs when loading a package for diff'ing
			const UPackage* Package = Object->GetOutermost();
			const bool bLoadedForDiff = (Package && Package->HasAnyPackageFlags(PKG_ForDiffing));
			if (!bLoadedForDiff && (!(Ar.GetPortFlags() & PPF_Duplicate) || (Ar.GetPortFlags() & PPF_DuplicateForPIE)))
			{
				check(!Guid.IsDefault());
				UObject* OtherObject = Guid.ResolveObject();
				if (OtherObject != Object) // on undo/redo, the object (potentially) already exists
				{
					if (OtherObject != NULL)
					{
						UE_CLOG(!((FApp::IsGame() || GIsPlayInEditorWorld) && Package && Package->ContainsMap()), LogUObjectGlobals, Warning, TEXT("Guid is in use by %s and %s, which should never happen in the editor but could happen at runtime with duplicate level loading or PIE"), *OtherObject->GetFullName(), !!Object ? *Object->GetFullName() : TEXT("NULL"));
						// This guid is in use, which should never happen in the editor but could happen at runtime with duplicate level loading or PIE. If so give it an invalid GUID and don't add to the annotation map.
						Guid = FGuid();
					}
					else
					{
						GuidAnnotation.AddAnnotation(Object, Guid);
					}
					FUniqueObjectGuid::InvalidateTag();
				}
			}
		}
	}
}
void UUserDefinedStruct::Serialize(FArchive& Ar)
{
	Super::Serialize( Ar );

	if (Ar.IsLoading() && (EUserDefinedStructureStatus::UDSS_UpToDate == Status))
	{
		// We need to force the editor data to be preload in case anyone needs to extract variable
		// information at editor time about the user structure.
		if ( EditorData != nullptr )
		{
			Ar.Preload(EditorData);
			if (!(Ar.GetPortFlags() & PPF_Duplicate))
			{
				FStructureEditorUtils::RecreateDefaultInstanceInEditorData(this);
			}
		}

		const FStructureEditorUtils::EStructureError Result = FStructureEditorUtils::IsStructureValid(this, NULL, &ErrorMessage);
		if (FStructureEditorUtils::EStructureError::Ok != Result)
		{
			Status = EUserDefinedStructureStatus::UDSS_Error;
			UE_LOG(LogClass, Log, TEXT("UUserDefinedStruct.Serialize '%s' validation: %s"), *GetName(), *ErrorMessage);
		}
	}
}
PRAGMA_POP

bool FStringAssetReference::Serialize(FArchive& Ar)
{
#if WITH_EDITOR
	if (Ar.IsSaving() && Ar.IsPersistent() && FCoreUObjectDelegates::StringAssetReferenceSaving.IsBound())
	{
		SetPath(FCoreUObjectDelegates::StringAssetReferenceSaving.Execute(ToString()));
	}
#endif // WITH_EDITOR
	Ar << *this;
#if WITH_EDITOR
	if (Ar.IsLoading() && Ar.IsPersistent() && FCoreUObjectDelegates::StringAssetReferenceLoaded.IsBound())
	{
		FCoreUObjectDelegates::StringAssetReferenceLoaded.Execute(ToString());
	}
#endif // WITH_EDITOR

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

	return true;
}
void UWorldComposition::Serialize( FArchive& Ar )
{
	Super::Serialize(Ar);
	
	// We serialize this data only for PIE
	// In normal game this data is regenerated on object construction
	if (Ar.GetPortFlags() & PPF_DuplicateForPIE)
	{
		Ar << WorldRoot;
		Ar << Tiles;
		Ar << TilesStreaming;
	}
}
Esempio n. 5
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);
	}
}
void UUserDefinedStruct::SerializeTaggedProperties(FArchive& Ar, uint8* Data, UStruct* DefaultsStruct, uint8* Defaults, const UObject* BreakRecursionIfFullyLoad) const
{
#if WITH_EDITOR
	/*	The following code is responsible for UUserDefinedStruct's default values serialization.	*/

	auto UDDefaultsStruct = Cast<UUserDefinedStruct>(DefaultsStruct);

	const bool bDuplicate = (0 != (Ar.GetPortFlags() & PPF_Duplicate));

	/*	When saving delta, we want the difference between current data and true structure's default values. 
		When Defaults is NULL then zeroed data will be used for comparison.*/
	const bool bUseNewDefaults = !Defaults
		&& UDDefaultsStruct
		&& Ar.DoDelta()
		&& Ar.IsSaving()
		&& !bDuplicate
		&& !Ar.IsCooking();

	/*	Object serialized from delta will have missing properties filled with zeroed data, 
		we want structure's default data instead */
	const bool bLoadDefaultFirst = UDDefaultsStruct
		&& !bDuplicate
		&& Ar.IsLoading();

	const bool bPrepareDefaultStruct = bUseNewDefaults || bLoadDefaultFirst;
	FStructOnScope StructDefaultMem(bPrepareDefaultStruct ? UDDefaultsStruct : NULL);
	if (bPrepareDefaultStruct)
	{
		FStructureEditorUtils::Fill_MakeStructureDefaultValue(UDDefaultsStruct, StructDefaultMem.GetStructMemory());
	}

	if (bUseNewDefaults)
	{
		Defaults = StructDefaultMem.GetStructMemory();
	}
	if (bLoadDefaultFirst)
	{
		if (Defaults == nullptr)
		{
			Defaults = StructDefaultMem.GetStructMemory();
		}
		UDDefaultsStruct->CopyScriptStruct(Data, Defaults);
	}
#endif // WITH_EDITOR
	Super::SerializeTaggedProperties(Ar, Data, DefaultsStruct, Defaults);
}
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);
}