void UK2Node_InputAxisEvent::Serialize(FArchive& Ar)
{
    Super::Serialize(Ar);

    if(Ar.IsLoading())
    {
        if(Ar.UE4Ver() < VER_UE4_K2NODE_EVENT_MEMBER_REFERENCE && EventSignatureName_DEPRECATED.IsNone() && EventSignatureClass_DEPRECATED == nullptr)
        {
            EventReference.SetExternalDelegateMember(TEXT("InputAxisHandlerDynamicSignature__DelegateSignature"));
        }
    }
}
예제 #2
0
	void Serialize(FArchive& Ar, UObject* Owner, int32 Idx)
    {
		const uint8 AdjacencyDataStripFlag = 1;
		FStripDataFlags StripFlags( Ar, Ar.IsCooking() && !Ar.CookingTarget()->SupportsFeature(ETargetPlatformFeatures::Tessellation) ? AdjacencyDataStripFlag : 0 );

		UStaticMesh* StaticMesh = Cast<UStaticMesh>( Owner );
		bool bNeedsCPUAccess = true;

		if( !StripFlags.IsEditorDataStripped() )
        {
			RawTriangles.Serialize( Ar, Owner );
        }

		Ar << Elements;

		if( !StripFlags.IsDataStrippedForServer() )
        {
			PositionVertexBuffer.Serialize( Ar, bNeedsCPUAccess );
			VertexBuffer.Serialize( Ar, bNeedsCPUAccess );
			ColorVertexBuffer.Serialize( Ar, bNeedsCPUAccess );
			Ar << NumVertices;
			IndexBuffer.Serialize( Ar, bNeedsCPUAccess );
			if (Ar.UE4Ver() >= VER_UE4_SHADOW_ONLY_INDEX_BUFFERS)
            {		
				ShadowIndexBuffer.Serialize(Ar, bNeedsCPUAccess);
            }
			if( !StripFlags.IsEditorDataStripped() )
            {
				Ar << WireframeIndexBuffer;
            }
			if ( !StripFlags.IsClassDataStripped( AdjacencyDataStripFlag ) )
            { 					
				AdjacencyIndexBuffer.Serialize( Ar, bNeedsCPUAccess );
            }
        }

		if (Ar.IsLoading())
        {
			if (PositionVertexBuffer.GetNumVertices() != NumVertices)
            {
				PositionVertexBuffer.RemoveLegacyShadowVolumeVertices(NumVertices);
			}
			if (VertexBuffer.GetNumVertices() != NumVertices)
			{
				VertexBuffer.RemoveLegacyShadowVolumeVertices(NumVertices);
			}
			if (VertexBuffer.GetNumVertices() != NumVertices)
            {				
				ColorVertexBuffer.RemoveLegacyShadowVolumeVertices(NumVertices);
			}
        }
    }										
void UK2Node_FunctionEntry::Serialize(FArchive& Ar)
{
	Super::Serialize(Ar);

	if (Ar.IsLoading())
	{
		if (Ar.UE4Ver() < VER_UE4_BLUEPRINT_ENFORCE_CONST_IN_FUNCTION_OVERRIDES)
		{
			// Allow legacy implementations to violate const-correctness
			bEnforceConstCorrectness = false;
		}
	}
}
void USoundNodeEnveloper::Serialize(FArchive& Ar)
{
	Super::Serialize(Ar);
	if (Ar.IsLoading())
	{
		if (Ar.UE4Ver() < VER_UE4_MOVE_DISTRIBUITONS_TO_POSTINITPROPS)
		{
			if (VolumeInterpCurve_DEPRECATED != NULL && VolumeInterpCurve_DEPRECATED->ConstantCurve.Points.Num() == 0)
			{
				VolumeCurve.EditorCurveData.AddKey(0.0f, 1.0f);
			}
			if (PitchInterpCurve_DEPRECATED != NULL && PitchInterpCurve_DEPRECATED->ConstantCurve.Points.Num() == 0)
			{
				PitchCurve.EditorCurveData.AddKey(0.0f, 1.0f);
			}
		}
		else if (Ar.UE4Ver() < VER_UE4_SOUND_NODE_ENVELOPER_CURVE_CHANGE)
		{
			if (VolumeInterpCurve_DEPRECATED)
			{
				VolumeCurve.EditorCurveData.Reset();
				for (int32 Index = 0; Index < VolumeInterpCurve_DEPRECATED->ConstantCurve.Points.Num(); ++Index)
				{
					FInterpCurvePoint<float>& Point = VolumeInterpCurve_DEPRECATED->ConstantCurve.Points[Index];
					VolumeCurve.EditorCurveData.AddKey(Point.InVal, Point.OutVal);
				}
			}
			if (PitchInterpCurve_DEPRECATED)
			{
				PitchCurve.EditorCurveData.Reset();
				for (int32 Index = 0; Index < PitchInterpCurve_DEPRECATED->ConstantCurve.Points.Num(); ++Index)
				{
					FInterpCurvePoint<float>& Point = PitchInterpCurve_DEPRECATED->ConstantCurve.Points[Index];
					PitchCurve.EditorCurveData.AddKey(Point.InVal, Point.OutVal);
				}
			}
		}
	}
}
예제 #5
0
void AWorldSettings::Serialize( FArchive& Ar )
{
	Super::Serialize(Ar);

	if (Ar.UE4Ver() < VER_UE4_ADD_OVERRIDE_GRAVITY_FLAG)
	{
		//before we had override flag we would use GlobalGravityZ != 0
		if(GlobalGravityZ != 0.0f)
		{
			bGlobalGravitySet = true;
		}
	}
}
void USoundNodeModulatorContinuous::Serialize(FArchive& Ar)
{
	Super::Serialize(Ar);
	if (Ar.IsLoading())
{
		if (Ar.UE4Ver() < VER_UE4_MOVE_DISTRIBUITONS_TO_POSTINITPROPS)
	{
			FDistributionHelpers::RestoreDefaultUniform(PitchModulation_DEPRECATED.Distribution, TEXT("DistributionPitch"), 0.95f, 1.05f);
			FDistributionHelpers::RestoreDefaultUniform(VolumeModulation_DEPRECATED.Distribution, TEXT("DistributionVolume"), 0.95f, 1.05f);
	}
		if (Ar.UE4Ver() < VER_UE4_MODULATOR_CONTINUOUS_NO_DISTRIBUTION)
		{
			// If it is a float sound parameter we convert, otherwise it will become a default 1.0 multiplier that has no effect
			UDEPRECATED_DistributionFloatSoundParameter* Distribution = Cast<UDEPRECATED_DistributionFloatSoundParameter>(PitchModulation_DEPRECATED.Distribution);
			if (Distribution)
			{
				PitchModulationParams.ParameterName = Distribution->ParameterName;
				PitchModulationParams.Default		= Distribution->Constant;
				PitchModulationParams.MinInput		= Distribution->MinInput;
				PitchModulationParams.MaxInput		= Distribution->MaxInput;
				PitchModulationParams.MinOutput		= Distribution->MinOutput;
				PitchModulationParams.MaxOutput		= Distribution->MaxOutput;
				PitchModulationParams.ParamMode		= (ModulationParamMode)(int32)Distribution->ParamMode;
}

			Distribution = Cast<UDEPRECATED_DistributionFloatSoundParameter>(VolumeModulation_DEPRECATED.Distribution);
			if (Distribution)
{
				VolumeModulationParams.ParameterName	= Distribution->ParameterName;
				VolumeModulationParams.Default			= Distribution->Constant;
				VolumeModulationParams.MinInput			= Distribution->MinInput;
				VolumeModulationParams.MaxInput			= Distribution->MaxInput;
				VolumeModulationParams.MinOutput		= Distribution->MinOutput;
				VolumeModulationParams.MaxOutput		= Distribution->MaxOutput;
				VolumeModulationParams.ParamMode		= (ModulationParamMode)(int32)Distribution->ParamMode;
			}
		}
	}
}
예제 #7
0
void FLinker::Serialize( FArchive& Ar )
{
	if( Ar.IsCountingMemory() )
	{
		// Can't use CountBytes as ExportMap is array of structs of arrays.
		Ar << ImportMap;
		Ar << ExportMap;
		Ar << DependsMap;

		if (Ar.IsSaving() || Ar.UE4Ver() >= VER_UE4_ADD_STRING_ASSET_REFERENCES_MAP)
		{
			Ar << StringAssetReferencesMap;
		}
	}

	if (Ar.IsSaving() || Ar.UE4Ver() >= VER_UE4_SERIALIZE_TEXT_IN_PACKAGES)
	{
		Ar << GatherableTextDataMap;
	}

	// Prevent garbage collecting of linker's names and package.
	Ar << NameMap << LinkerRoot;
	{
		for (auto& E : ExportMap)
		{
			Ar << E.ObjectName;
		}
	}
	{
		for (auto& I : ImportMap)
		{
			UObject* LegacyLinkerObject = nullptr;
			Ar << LegacyLinkerObject;
			Ar << I.ClassPackage << I.ClassName;
		}
	}

}
예제 #8
0
void FRawCurveTracks::Serialize(FArchive& Ar)
{
	// @TODO: If we're about to serialize vector curve, add here
	if(Ar.UE4Ver() >= VER_UE4_SKELETON_ADD_SMARTNAMES)
	{
		for(FFloatCurve& Curve : FloatCurves)
		{
			Curve.Serialize(Ar);
		}
	}
#if WITH_EDITORONLY_DATA
	if( !Ar.IsCooking() )
	{
		if( Ar.UE4Ver() >= VER_UE4_ANIMATION_ADD_TRACKCURVES )
		{
			for( FTransformCurve& Curve : TransformCurves )
			{
				Curve.Serialize( Ar );
			}

		}
	}
#endif // WITH_EDITORONLY_DATA
}
예제 #9
0
void FGraphReference::PostSerialize(const FArchive& Ar)
{
#if WITH_EDITORONLY_DATA
	if (Ar.UE4Ver() >= VER_UE4_K2NODE_REFERENCEGUIDS)
	{
		// Because the macro instance could have been saved with a GUID that was allocated 
		// but the macro graph never actually saved with that value we are forced to make 
		// sure to refresh the GUID and make sure it is up to date
		if (MacroGraph)
		{
			GraphGuid = MacroGraph->GraphGuid;
		}
	}
#endif
}
예제 #10
0
void FConstraintInstance::PostSerialize(const FArchive& Ar)
{
	if (Ar.IsLoading() && Ar.UE4Ver() < VER_UE4_FIXUP_STIFFNESS_AND_DAMPING_SCALE)
	{
		LinearLimitStiffness	/= CVarConstraintStiffnessScale.GetValueOnGameThread();
		SwingLimitStiffness		/= CVarConstraintStiffnessScale.GetValueOnGameThread();
		TwistLimitStiffness		/= CVarConstraintStiffnessScale.GetValueOnGameThread();
		LinearLimitDamping		/=  CVarConstraintDampingScale.GetValueOnGameThread();
		SwingLimitDamping		/=  CVarConstraintDampingScale.GetValueOnGameThread();
		TwistLimitDamping		/=  CVarConstraintDampingScale.GetValueOnGameThread();
	}

	if (Ar.IsLoading() && Ar.UE4Ver() < VER_UE4_FIXUP_MOTOR_UNITS)
	{
		AngularVelocityTarget *= 1.f / (2.f * PI);	//we want to use revolutions per second - old system was using radians directly
	}

	if (Ar.IsLoading() && Ar.UE4Ver() < VER_UE4_CONSTRAINT_INSTANCE_MOTOR_FLAGS)
	{
		bLinearXVelocityDrive = LinearVelocityTarget.X != 0.f;
		bLinearYVelocityDrive = LinearVelocityTarget.Y != 0.f;
		bLinearZVelocityDrive = LinearVelocityTarget.Z != 0.f;
	}
}
예제 #11
0
void FTextHistory_AsCurrency::Serialize( FArchive& Ar )
{
	if(Ar.IsSaving())
	{
		int8 HistoryType = (int8)ETextHistoryType::AsCurrency;
		Ar << HistoryType;
	}

	if (Ar.UE4Ver() >= VER_UE4_ADDED_CURRENCY_CODE_TO_FTEXT)
	{
		Ar << CurrencyCode;
	}

	FTextHistory_FormatNumber::Serialize(Ar);
}
bool FGameplayTagContainer::Serialize(FArchive& Ar)
{
	const bool bOldTagVer = Ar.UE4Ver() < VER_UE4_GAMEPLAY_TAG_CONTAINER_TAG_TYPE_CHANGE;
	
	if (bOldTagVer)
	{
		Ar << Tags_DEPRECATED;
	}
	else
	{
		Ar << GameplayTags;
	}
	
	if (Ar.IsLoading())
	{
		UGameplayTagsManager& TagManager = IGameplayTagsModule::GetGameplayTagsManager();

		// If loading old version, add old tags to the new gameplay tags array so they can be saved out with the new version
		// This needs to happen 
		// NOTE: DeprecatedTagNamesNotFoundInTagMap should be removed along with the bOldTagVer when we remove backwards
		// compatibility, and the signature of RedirectTagsForContainer (below) should be changed appropriately as well.
		TSet<FName> DeprecatedTagNamesNotFoundInTagMap;
		if (bOldTagVer)
		{
			for (auto It = Tags_DEPRECATED.CreateConstIterator(); It; ++It)
			{
				const bool bErrorIfNotFound = false;
				FGameplayTag Tag = TagManager.RequestGameplayTag(*It, bErrorIfNotFound);
				if (Tag.IsValid())
				{
					TagManager.AddLeafTagToContainer(*this, Tag);
				}
				else
				{	// For tags not found in the current table, add them to a list to be checked when handling
					// redirection (below).
					DeprecatedTagNamesNotFoundInTagMap.Add(*It);
				}
			}
		}

		// Rename any tags that may have changed by the ini file.  Redirects can happen regardless of version.
		// Regardless of version, want loading to have a chance to handle redirects
		TagManager.RedirectTagsForContainer(*this, DeprecatedTagNamesNotFoundInTagMap);
	}

	return true;
}
예제 #13
0
void ULightComponent::Serialize(FArchive& Ar)
{
	Super::Serialize(Ar);

	if (Ar.UE4Ver() >= VER_UE4_STATIC_SHADOW_DEPTH_MAPS)
	{
		if (Ar.IsCooking() && !Ar.CookingTarget()->SupportsFeature(ETargetPlatformFeatures::HighQualityLightmaps))
		{
			// Toss lighting data only needed for high quality lightmaps
			FStaticShadowDepthMap EmptyDepthMap;
			Ar << EmptyDepthMap;
		}
		else
		{
			Ar << StaticShadowDepthMap;
		}
	}
}
예제 #14
0
void FKAggregateGeom::Serialize( const FArchive& Ar )
{
	if ( Ar.IsLoading() && Ar.UE4Ver() < VER_UE4_REFACTOR_PHYSICS_TRANSFORMS )
	{
		for ( auto SphereElemIt = SphereElems.CreateIterator(); SphereElemIt; ++SphereElemIt )
		{
			SphereElemIt->Serialize( Ar );
		}

		for ( auto BoxElemIt = BoxElems.CreateIterator(); BoxElemIt; ++BoxElemIt )
		{
			BoxElemIt->Serialize( Ar );
		}

		for ( auto SphylElemIt = SphylElems.CreateIterator(); SphylElemIt; ++SphylElemIt )
		{
			SphylElemIt->Serialize( Ar );
		}
	}
}
예제 #15
0
bool FRichCurveKey::Serialize(FArchive& Ar)
{
	if (Ar.UE4Ver() < VER_UE4_SERIALIZE_RICH_CURVE_KEY)
	{
		return false;
	}

	// Serialization is handled manually to avoid the extra size overhead of UProperty tagging.
	// Otherwise with many keys in a rich curve the size can become quite large.
	Ar << InterpMode;
	Ar << TangentMode;
	Ar << TangentWeightMode;
	Ar << Time;
	Ar << Value;
	Ar << ArriveTangent;
	Ar << ArriveTangentWeight;
	Ar << LeaveTangent;
	Ar << LeaveTangentWeight;

	return true;
}
예제 #16
0
bool FMovieSceneSpawnable::Serialize(FArchive& Ar)
{
	Ar << Guid;
	Ar << Name;

#if WITH_EDITOR
	if (Ar.IsLoading() && Ar.UE4Ver() < VER_UE4_EDITORONLY_BLUEPRINTS)
	{
		UBlueprint* ObsoleteBlueprint = NULL;
		Ar << ObsoleteBlueprint;
		if(ObsoleteBlueprint)
		{
			GeneratedClass = ObsoleteBlueprint->GeneratedClass;
		}
	}
	else
#endif //WITH_EDITOR
	{
		Ar << GeneratedClass;
	}
	return true;
}
예제 #17
0
void FRawStaticIndexBuffer::Serialize(FArchive& Ar, bool bNeedsCPUAccess)
{
	IndexStorage.SetAllowCPUAccess(bNeedsCPUAccess);

	if (Ar.UE4Ver() < VER_UE4_SUPPORT_32BIT_STATIC_MESH_INDICES)
	{
		TResourceArray<uint16,INDEXBUFFER_ALIGNMENT> LegacyIndices;

		b32Bit = false;
		LegacyIndices.BulkSerialize(Ar);
		int32 NumIndices = LegacyIndices.Num();
		int32 IndexStride = sizeof(uint16);
		IndexStorage.Empty(NumIndices * IndexStride);
		IndexStorage.AddUninitialized(NumIndices * IndexStride);
		FMemory::Memcpy(IndexStorage.GetData(),LegacyIndices.GetData(),IndexStorage.Num());
	}
	else
	{
		Ar << b32Bit;
		IndexStorage.BulkSerialize(Ar);
	}
}
예제 #18
0
void UAssetImportData::Serialize(FArchive& Ar)
{
	if (Ar.UE4Ver() >= VER_UE4_ASSET_IMPORT_DATA_AS_JSON)
	{
		FString Json;
		if (Ar.IsLoading())
		{
			Ar << Json;
			TOptional<FAssetImportInfo> Copy = FromJson(MoveTemp(Json));
			if (Copy.IsSet())
			{
				CopyFrom(Copy.GetValue());
			}
		}
		else if (Ar.IsSaving())
		{
			Json = ToJson();
			Ar << Json;
		}
	}

	Super::Serialize(Ar);
}
예제 #19
0
void FSmartNameMapping::Serialize(FArchive& Ar)
{
	if(Ar.UE4Ver() >= VER_UE4_SKELETON_ADD_SMARTNAMES)
	{
		Ar << NextUid;
		Ar << UidMap;

		if(Ar.ArIsLoading)
		{
			// Sort the Uid Map
			UidMap.KeySort([](const UID& A, const UID& B)
			{
				return A < B;
			});

			// Build freelist as necessary
			UID ExpectedID = 0;
			UID Last = 0;
			for(TPair<UID, FName>& Pair : UidMap)
			{
				UID CurrentUid = Pair.Key;
				while(CurrentUid != ExpectedID)
				{
					FreeList.Add(ExpectedID++);
				}

				Last = CurrentUid;
				++ExpectedID;
			}

			// In the case of multipled queued deletions previously,
			// fix up the next UID to match the last used key we found.
			NextUid = Last + 1;
		}
	}
}
예제 #20
0
void USoundWave::Serialize( FArchive& Ar )
{
	DECLARE_SCOPE_CYCLE_COUNTER( TEXT("USoundWave::Serialize"), STAT_SoundWave_Serialize, STATGROUP_LoadTime );

	Super::Serialize( Ar );

	bool bCooked = Ar.IsCooking();
	Ar << bCooked;

	if (FPlatformProperties::RequiresCookedData() && !bCooked && Ar.IsLoading())
	{
		UE_LOG(LogAudio, Fatal, TEXT("This platform requires cooked packages, and audio data was not cooked into %s."), *GetFullName());
	}

	Ar.UsingCustomVersion(FFrameworkObjectVersion::GUID);

	if (Ar.IsLoading() && (Ar.UE4Ver() >= VER_UE4_SOUND_COMPRESSION_TYPE_ADDED) && (Ar.CustomVer(FFrameworkObjectVersion::GUID) < FFrameworkObjectVersion::RemoveSoundWaveCompressionName))
	{
		FName DummyCompressionName;
		Ar << DummyCompressionName;
	}

	bool bSupportsStreaming = false;
	if (Ar.IsLoading() && FPlatformProperties::SupportsAudioStreaming())
	{
		bSupportsStreaming = true;
	}
	else if (Ar.IsCooking() && Ar.CookingTarget()->SupportsFeature(ETargetPlatformFeatures::AudioStreaming))
	{
		bSupportsStreaming = true;
	}

	if (bCooked)
	{
		// Only want to cook/load full data if we don't support streaming
		if (!IsStreaming() || !bSupportsStreaming)
		{
			if (Ar.IsCooking())
			{
#if WITH_ENGINE
				TArray<FName> ActualFormatsToSave;
				if (!Ar.CookingTarget()->IsServerOnly())
				{
					// for now we only support one format per wav
					FName Format = Ar.CookingTarget()->GetWaveFormat(this);
					GetCompressedData(Format); // Get the data from the DDC or build it

					ActualFormatsToSave.Add(Format);
				}
				CompressedFormatData.Serialize(Ar, this, &ActualFormatsToSave);
#endif
			}
			else
			{
				CompressedFormatData.Serialize(Ar, this);
			}
		}
	}
	else
	{
		// only save the raw data for non-cooked packages
		RawData.Serialize( Ar, this );
	}

	Ar << CompressedDataGuid;

	if (IsStreaming())
	{
		if (bCooked)
		{
			// only cook/load streaming data if it's supported
			if (bSupportsStreaming)
			{
				SerializeCookedPlatformData(Ar);
			}
		}

#if WITH_EDITORONLY_DATA	
		if (Ar.IsLoading() && !Ar.IsTransacting() && !bCooked && !GetOutermost()->HasAnyPackageFlags(PKG_ReloadingForCooker))
		{
			BeginCachePlatformData();
		}
#endif // #if WITH_EDITORONLY_DATA
	}
}
예제 #21
0
void USoundWave::Serialize( FArchive& Ar )
{
	Super::Serialize( Ar );

	bool bCooked = Ar.IsCooking();
	Ar << bCooked;

	if (FPlatformProperties::RequiresCookedData() && !bCooked && Ar.IsLoading())
	{
		UE_LOG(LogAudio, Fatal, TEXT("This platform requires cooked packages, and audio data was not cooked into %s."), *GetFullName());
	}

	if (Ar.IsCooking())
	{
		CompressionName = Ar.CookingTarget()->GetWaveFormat(this);
	}
	
	if (Ar.UE4Ver() >= VER_UE4_SOUND_COMPRESSION_TYPE_ADDED)
	{
		Ar << CompressionName;
	}

	if (bCooked)
	{
		// Only want to cook/load full data if we don't support streaming
		if (!IsStreaming() ||
			(Ar.IsLoading() && !FPlatformProperties::SupportsAudioStreaming()) ||
			(Ar.IsCooking() && !Ar.CookingTarget()->SupportsFeature(ETargetPlatformFeatures::AudioStreaming)))
		{
			if (Ar.IsCooking())
			{
#if WITH_ENGINE
				TArray<FName> ActualFormatsToSave;
				if (!Ar.CookingTarget()->IsServerOnly())
				{
					// for now we only support one format per wav
					FName Format = Ar.CookingTarget()->GetWaveFormat(this);
					GetCompressedData(Format); // Get the data from the DDC or build it

					ActualFormatsToSave.Add(Format);
				}
				CompressedFormatData.Serialize(Ar, this, &ActualFormatsToSave);
#endif
			}
			else
			{
				CompressedFormatData.Serialize(Ar, this);
			}
		}
	}
	else
	{
		// only save the raw data for non-cooked packages
		RawData.Serialize( Ar, this );
	}

	Ar << CompressedDataGuid;

	if (IsStreaming())
	{
		if (bCooked)
		{
			// only cook/load streaming data if it's supported
			if ((Ar.IsLoading() && FPlatformProperties::SupportsAudioStreaming()) ||
				(Ar.IsCooking() && Ar.CookingTarget()->SupportsFeature(ETargetPlatformFeatures::AudioStreaming)))
			{
				SerializeCookedPlatformData(Ar);
			}
		}

#if WITH_EDITORONLY_DATA	
		if (Ar.IsLoading() && !Ar.IsTransacting() && !bCooked && !(GetOutermost()->PackageFlags & PKG_ReloadingForCooker))
		{
			BeginCachePlatformData();
		}
#endif // #if WITH_EDITORONLY_DATA
	}
}
void UReflectionCaptureComponent::Serialize(FArchive& Ar)
{
	Super::Serialize(Ar);

	bool bCooked = false;

	if (Ar.UE4Ver() >= VER_UE4_REFLECTION_CAPTURE_COOKING)
	{
		bCooked = Ar.IsCooking();
		// Save a bool indicating whether this is cooked data
		// This is needed when loading cooked data, to know to serialize differently
		Ar << bCooked;
	}

	if (FPlatformProperties::RequiresCookedData() && !bCooked && Ar.IsLoading())
	{
		UE_LOG(LogMaterial, Fatal, TEXT("This platform requires cooked packages, and this reflection capture does not contain cooked data %s."), *GetName());
	}

	if (bCooked)
	{
		static FName FullHDR(TEXT("FullHDR"));
		static FName EncodedHDR(TEXT("EncodedHDR"));

		// Saving for cooking path
		if (Ar.IsCooking())
		{
			// Get all the reflection capture formats that the target platform wants
			TArray<FName> Formats;
			Ar.CookingTarget()->GetReflectionCaptureFormats(Formats);

			int32 NumFormats = Formats.Num();
			Ar << NumFormats;

			for (int32 FormatIndex = 0; FormatIndex < NumFormats; FormatIndex++)
			{
				FName CurrentFormat = Formats[FormatIndex];

				Ar << CurrentFormat;

				if (CurrentFormat == FullHDR)
				{
					// FullHDRDerivedData would have been set in PostLoad during cooking if it exists in the DDC
					// Can't generate it if missing, since that requires rendering the scene
					bool bValid = FullHDRDerivedData != NULL;

					Ar << bValid;

					if (bValid)
					{
						Ar << FullHDRDerivedData->CompressedCapturedData;
					}
				}
				else
				{
					check(CurrentFormat == EncodedHDR);

					TRefCountPtr<FReflectionCaptureEncodedHDRDerivedData> EncodedHDRData;
					
					// FullHDRDerivedData would have been set in PostLoad during cooking if it exists in the DDC
					// Generate temporary encoded HDR data for saving
					if (FullHDRDerivedData != NULL)
					{
						EncodedHDRData = FReflectionCaptureEncodedHDRDerivedData::GenerateEncodedHDRData(*FullHDRDerivedData, StateId, Brightness);
					}
					
					bool bValid = EncodedHDRData != NULL;

					Ar << bValid;

					if (bValid)
					{
						Ar << EncodedHDRData->CapturedData;
					}
					else if (!IsTemplate())
					{
						// Temporary warning until the cooker can do scene captures itself in the case of missing DDC
						UE_LOG(LogMaterial, Warning, TEXT("Reflection capture requires encoded HDR data but none was found in the DDC!  This reflection will be black.  Fix by loading the map in the editor once.  %s."), *GetFullName());
					}
				}
			}
		}
		else
		{
			// Loading cooked data path

			int32 NumFormats = 0;
			Ar << NumFormats;

			for (int32 FormatIndex = 0; FormatIndex < NumFormats; FormatIndex++)
			{
				FName CurrentFormat;
				Ar << CurrentFormat;

				bool bValid = false;
				Ar << bValid;

				if (bValid)
				{
					if (CurrentFormat == FullHDR)
					{
						FullHDRDerivedData = new FReflectionCaptureFullHDRDerivedData();
						Ar << FullHDRDerivedData->CompressedCapturedData;
					}
					else 
					{
						check(CurrentFormat == EncodedHDR);
						EncodedHDRDerivedData = new FReflectionCaptureEncodedHDRDerivedData();
						Ar << EncodedHDRDerivedData->CapturedData;
					}
				}
				else if (CurrentFormat == EncodedHDR)
				{
					// Temporary warning until the cooker can do scene captures itself in the case of missing DDC
					UE_LOG(LogMaterial, Error, TEXT("Reflection capture was loaded without any valid capture data and will be black.  This can happen if the DDC was not up to date during cooking.  Load the map in the editor once before cooking to fix.  %s."), *GetFullName());
				}
			}
		}
	}
}
예제 #23
0
void UArrayProperty::SerializeItem( FArchive& Ar, void* Value, void const* Defaults ) const
{
	checkSlow(Inner);

	// Ensure that the Inner itself has been loaded before calling SerializeItem() on it
	Ar.Preload(Inner);

	FScriptArrayHelper ArrayHelper(this, Value);
	int32		n		= ArrayHelper.Num();
	Ar << n;
	if( Ar.IsLoading() )
	{
		// If using a custom property list, don't empty the array on load. Not all indices may have been serialized, so we need to preserve existing values at those slots.
		if (Ar.ArUseCustomPropertyList)
		{
			const int32 OldNum = ArrayHelper.Num();
			if (n > OldNum)
			{
				ArrayHelper.AddValues(n - OldNum);
			}
			else if (n < OldNum)
			{
				ArrayHelper.RemoveValues(n, OldNum - n);
			}
		}
		else
		{
			ArrayHelper.EmptyAndAddValues(n);
		}
	}
	ArrayHelper.CountBytes( Ar );

	// Serialize a PropertyTag for the inner property of this array, allows us to validate the inner struct to see if it has changed
	FPropertyTag InnerTag(Ar, Inner, 0, (uint8*)Value, (uint8*)Defaults);
	if (Ar.UE4Ver() >= VER_UE4_INNER_ARRAY_TAG_INFO && InnerTag.Type == NAME_StructProperty)
	{
		if (Ar.IsSaving())
		{
			Ar << InnerTag;
		}
		else if (Ar.IsLoading())
		{
			Ar << InnerTag;

			auto CanSerializeFromStructWithDifferentName = [](const FArchive& InAr, const FPropertyTag& PropertyTag, const UStructProperty* StructProperty)
			{
				return PropertyTag.StructGuid.IsValid()
					&& StructProperty 
					&& StructProperty->Struct 
					&& (PropertyTag.StructGuid == StructProperty->Struct->GetCustomGuid());
			};

			// Check if the Inner property can successfully serialize, the type may have changed
			UStructProperty* StructProperty = CastChecked<UStructProperty>(Inner);
			// if check redirector to make sure if the name has changed
			FName* NewName = FLinkerLoad::StructNameRedirects.Find(InnerTag.StructName);
			FName StructName = CastChecked<UStructProperty>(StructProperty)->Struct->GetFName();
			if (NewName != nullptr && *NewName == StructName)
			{
				InnerTag.StructName = *NewName;
			}

			if (InnerTag.StructName != StructProperty->Struct->GetFName()
				&& !CanSerializeFromStructWithDifferentName(Ar, InnerTag, StructProperty))
			{
				UE_LOG(LogClass, Warning, TEXT("Property %s of %s has a struct type mismatch (tag %s != prop %s) in package:  %s. If that struct got renamed, add an entry to ActiveStructRedirects."),
					*InnerTag.Name.ToString(), *GetName(), *InnerTag.StructName.ToString(), *CastChecked<UStructProperty>(Inner)->Struct->GetName(), *Ar.GetArchiveName());

#if WITH_EDITOR
				// Ensure the structure is initialized
				for (int32 i = 0; i < n; i++)
				{
					StructProperty->Struct->InitializeDefaultValue(ArrayHelper.GetRawPtr(i));
				}
#endif // WITH_EDITOR

				// Skip the property
				const int64 StartOfProperty = Ar.Tell();
				const int64 RemainingSize = InnerTag.Size - (Ar.Tell() - StartOfProperty);
				uint8 B;
				for (int64 i = 0; i < RemainingSize; i++)
				{
					Ar << B;
				}
				return;
			}
		}
	}

	// need to know how much data this call to SerializeItem consumes, so mark where we are
	int32 DataOffset = Ar.Tell();

	// If we're using a custom property list, first serialize any explicit indices
	int32 i = 0;
	bool bSerializeRemainingItems = true;
	bool bUsingCustomPropertyList = Ar.ArUseCustomPropertyList;
	if (bUsingCustomPropertyList && Ar.ArCustomPropertyList != nullptr)
	{
		// Initially we only serialize indices that are explicitly specified (in order)
		bSerializeRemainingItems = false;

		const FCustomPropertyListNode* CustomPropertyList = Ar.ArCustomPropertyList;
		const FCustomPropertyListNode* PropertyNode = CustomPropertyList;
		while (PropertyNode && i < n && !bSerializeRemainingItems)
		{
			if (PropertyNode->Property != Inner)
			{
				// A null property value signals that we should serialize the remaining array values in full starting at this index
				if (PropertyNode->Property == nullptr)
				{
					i = PropertyNode->ArrayIndex;
				}

				bSerializeRemainingItems = true;
			}
			else
			{
				// Set a temporary node to represent the item
				FCustomPropertyListNode ItemNode = *PropertyNode;
				ItemNode.ArrayIndex = 0;
				ItemNode.PropertyListNext = nullptr;
				Ar.ArCustomPropertyList = &ItemNode;

				// Serialize the item at this array index
				i = PropertyNode->ArrayIndex;
				Inner->SerializeItem(Ar, ArrayHelper.GetRawPtr(i));
				PropertyNode = PropertyNode->PropertyListNext;

				// Restore the current property list
				Ar.ArCustomPropertyList = CustomPropertyList;
			}
		}
	}

	if (bSerializeRemainingItems)
	{
		// Temporarily suspend the custom property list (as we need these items to be serialized in full)
		Ar.ArUseCustomPropertyList = false;

		// Serialize each item until we get to the end of the array
		while (i < n)
		{
			Inner->SerializeItem(Ar, ArrayHelper.GetRawPtr(i++));
		}

		// Restore use of the custom property list (if it was previously enabled)
		Ar.ArUseCustomPropertyList = bUsingCustomPropertyList;
	}

	if (Ar.UE4Ver() >= VER_UE4_INNER_ARRAY_TAG_INFO && Ar.IsSaving() && InnerTag.Type == NAME_StructProperty)
	{
		// set the tag's size
		InnerTag.Size = Ar.Tell() - DataOffset;

		if (InnerTag.Size > 0)
		{
			// mark our current location
			DataOffset = Ar.Tell();

			// go back and re-serialize the size now that we know it
			Ar.Seek(InnerTag.SizeOffset);
			Ar << InnerTag.Size;

			// return to the current location
			Ar.Seek(DataOffset);
		}
	}
}
예제 #24
0
void UModel::Serialize( FArchive& Ar )
{
	Super::Serialize( Ar );

	const int32 StripVertexBufferFlag = 1;
	FStripDataFlags StripFlags( Ar, GetOuter() && GetOuter()->IsA(ABrush::StaticClass()) ? StripVertexBufferFlag : FStripDataFlags::None );

	Ar << Bounds;

	if (Ar.IsLoading() && Ar.UE4Ver() < VER_UE4_BSP_UNDO_FIX )
	{
		TTransArray<FVector> OldVectors(this);
		TTransArray<FVector> OldPoints(this);
		TTransArray<FBspNode> OldNodes(this);
		OldVectors.BulkSerialize(Ar);
		OldPoints.BulkSerialize(Ar);
		OldNodes.BulkSerialize(Ar);

		Vectors = OldVectors;
		Points = OldPoints;
		Nodes = OldNodes;
	}
	else
	{
		Vectors.BulkSerialize(Ar);
		Points.BulkSerialize(Ar);
		Nodes.BulkSerialize(Ar);
	}
	if( Ar.IsLoading() )
	{
		for( int32 NodeIndex=0; NodeIndex<Nodes.Num(); NodeIndex++ )
		{
			Nodes[NodeIndex].NodeFlags &= ~(NF_IsNew|NF_IsFront|NF_IsBack);
		}
	}
	
	if (Ar.IsLoading() && Ar.UE4Ver() < VER_UE4_BSP_UNDO_FIX )
	{
		TTransArray<FBspSurf> OldSurfs(this);
		TTransArray<FVert> OldVerts(this);

		Ar << OldSurfs;
		OldVerts.BulkSerialize(Ar);

		Surfs = OldSurfs;
		Verts = OldVerts;
	}
	else
	{
		Ar << Surfs;
		Verts.BulkSerialize(Ar);
	}

	if( Ar.IsLoading() && Ar.UE4Ver() < VER_UE4_REMOVE_ZONES_FROM_MODEL)
	{
		int32 NumZones;
		Ar << NumSharedSides << NumZones;

		FZoneProperties DummyZones[FBspNode::MAX_ZONES];
		for( int32 i=0; i<NumZones; i++ )
		{
			Ar << DummyZones[i];
		}
	}
	else
	{
		Ar << NumSharedSides;
	}

#if WITH_EDITOR
	bool bHasEditorOnlyData = !Ar.IsFilterEditorOnly();
	
	if ( Ar.UE4Ver() < VER_UE4_REMOVE_UNUSED_UPOLYS_FROM_UMODEL )
	{
		bHasEditorOnlyData = true;
	}

	// if we are cooking then don't save this stuff out
	if ( bHasEditorOnlyData )
	{
		Ar << Polys;
		LeafHulls.BulkSerialize( Ar );
		Leaves.BulkSerialize( Ar );
	}
#else
	bool bHasEditorOnlyData = !Ar.IsFilterEditorOnly();
	
	if ( Ar.UE4Ver() < VER_UE4_REMOVE_UNUSED_UPOLYS_FROM_UMODEL )
	{
		bHasEditorOnlyData = true;
	}

	if((Ar.IsLoading() || Ar.IsSaving()) && bHasEditorOnlyData)
	{
		UPolys* DummyPolys = NULL;
		Ar << DummyPolys;

		TArray<int32> DummyLeafHulls;
		DummyLeafHulls.BulkSerialize( Ar );

		TArray<FLeaf> DummyLeaves;
		DummyLeaves.BulkSerialize( Ar );
	}
#endif

	Ar << RootOutside << Linked;

	if(Ar.IsLoading() && Ar.UE4Ver() < VER_UE4_REMOVE_ZONES_FROM_MODEL)
	{
		TArray<int32> DummyPortalNodes;
		DummyPortalNodes.BulkSerialize( Ar );
	}

	Ar << NumUniqueVertices; 
	// load/save vertex buffer
	if( StripFlags.IsEditorDataStripped() == false || StripFlags.IsClassDataStripped( StripVertexBufferFlag ) == false )
	{
		Ar << VertexBuffer;
	}

#if WITH_EDITOR
	if(GIsEditor)
	{
		CalculateUniqueVertCount();
	}
#endif // WITH_EDITOR

	// serialize the lighting guid if it's there
	Ar << LightingGuid;

	Ar << LightmassSettings;
}
void USpineSkeletonDataAsset::Serialize (FArchive& Ar) {
	Super::Serialize(Ar);
	if (Ar.IsLoading() && Ar.UE4Ver() < VER_UE4_ASSET_IMPORT_DATA_AS_JSON && !importData)
		importData = NewObject<UAssetImportData>(this, TEXT("AssetImportData"));
}
void USimpleConstructionScript::Serialize(FArchive& Ar)
{
	Super::Serialize(Ar);

	if(Ar.IsLoading())
	{
		if(Ar.UE4Ver() < VER_UE4_REMOVE_NATIVE_COMPONENTS_FROM_BLUEPRINT_SCS)
		{
			// If we previously had a root node, we need to move it into the new RootNodes array. This is done in Serialize() in order to support SCS preloading (which relies on a valid RootNodes array).
			if(RootNode_DEPRECATED != NULL)
			{
				// Ensure it's been loaded so that its properties are valid
				if(RootNode_DEPRECATED->HasAnyFlags(RF_NeedLoad))
				{
					RootNode_DEPRECATED->GetLinker()->Preload(RootNode_DEPRECATED);
				}

				// If the root node was not native
				if(!RootNode_DEPRECATED->bIsNative_DEPRECATED)
				{
					// Add the node to the root set
					RootNodes.Add(RootNode_DEPRECATED);
				}
				else
				{
					// For each child of the previously-native root node
					for (USCS_Node* Node : RootNode_DEPRECATED->GetChildNodes())
					{
						if(Node != NULL)
						{
							// Ensure it's been loaded (may not have been yet if we're preloading the SCS)
							if(Node->HasAnyFlags(RF_NeedLoad))
							{
								Node->GetLinker()->Preload(Node);
							}

							// We only care about non-native child nodes (non-native nodes could only be attached to the root node in the previous version, so we don't need to examine native child nodes)
							if(!Node->bIsNative_DEPRECATED)
							{
								// Add the node to the root set
								RootNodes.Add(Node);

								// Set the previously-native root node as its parent component
								Node->bIsParentComponentNative = true;
								Node->ParentComponentOrVariableName = RootNode_DEPRECATED->NativeComponentName_DEPRECATED;
							}
						}
					}
				}

				// Clear the deprecated reference
				RootNode_DEPRECATED = NULL;
			}

			// Add any user-defined actor components to the root set
			for (USCS_Node* Node : ActorComponentNodes_DEPRECATED)
			{
				if(Node != NULL)
				{
					// Ensure it's been loaded (may not have been yet if we're preloading the SCS)
					if(Node->HasAnyFlags(RF_NeedLoad))
					{
						Node->GetLinker()->Preload(Node);
					}

					if(!Node->bIsNative_DEPRECATED)
					{
						RootNodes.Add(Node);
					}
				}
			}

			// Clear the deprecated ActorComponent list
			ActorComponentNodes_DEPRECATED.Empty();
		}
	}
}
예제 #27
0
void USkeleton::Serialize( FArchive& Ar )
{
	Super::Serialize(Ar);

	if( Ar.UE4Ver() >= VER_UE4_REFERENCE_SKELETON_REFACTOR )
	{
		Ar << ReferenceSkeleton;
	}

	if (Ar.UE4Ver() >= VER_UE4_FIX_ANIMATIONBASEPOSE_SERIALIZATION)
	{
		// Load Animation RetargetSources
		if (Ar.IsLoading())
		{
			int32 NumOfRetargetSources;
			Ar << NumOfRetargetSources;

			FName RetargetSourceName;
			FReferencePose RetargetSource;
			for (int32 Index=0; Index<NumOfRetargetSources; ++Index)
			{
				Ar << RetargetSourceName;
				Ar << RetargetSource;

				AnimRetargetSources.Add(RetargetSourceName, RetargetSource);
			}
		}
		else 
		{
			int32 NumOfRetargetSources = AnimRetargetSources.Num();
			Ar << NumOfRetargetSources;

			for (auto Iter = AnimRetargetSources.CreateIterator(); Iter; ++Iter)
			{
				Ar << Iter.Key();
				Ar << Iter.Value();
			}
		}
	}
	else
	{
		// this is broken, but we have to keep it to not corrupt content. 
		for (auto Iter = AnimRetargetSources.CreateIterator(); Iter; ++Iter)
		{
			Ar << Iter.Key();
			Ar << Iter.Value();
		}
	}

	if (Ar.UE4Ver() < VER_UE4_SKELETON_GUID_SERIALIZATION)
	{
		RegenerateGuid();
	}
	else
	{
		Ar << Guid;
	}

	// If we should be using smartnames, serialize the mappings
	if(Ar.UE4Ver() >= VER_UE4_SKELETON_ADD_SMARTNAMES)
	{
		SmartNames.Serialize(Ar);
	}

#if WITH_EDITORONLY_DATA
	if (Ar.UE4Ver() < VER_UE4_SKELETON_ASSET_PROPERTY_TYPE_CHANGE)
	{
		PreviewAttachedAssetContainer.SaveAttachedObjectsFromDeprecatedProperties();
	}
#endif
}
예제 #28
0
void FReverbSettings::PostSerialize(const FArchive& Ar)
{
	if( Ar.UE4Ver() < VER_UE4_REVERB_EFFECT_ASSET_TYPE )
	{
		FString ReverbAssetName;
		switch(ReverbType_DEPRECATED)
		{
			case REVERB_Default:
				// No replacement asset for default reverb type
				return;

			case REVERB_Bathroom:
				ReverbAssetName = TEXT("/Engine/EngineSounds/ReverbSettings/Bathroom.Bathroom");
				break;

			case REVERB_StoneRoom:
				ReverbAssetName = TEXT("/Engine/EngineSounds/ReverbSettings/StoneRoom.StoneRoom");
				break;

			case REVERB_Auditorium:
				ReverbAssetName = TEXT("/Engine/EngineSounds/ReverbSettings/Auditorium.Auditorium");
				break;

			case REVERB_ConcertHall:
				ReverbAssetName = TEXT("/Engine/EngineSounds/ReverbSettings/ConcertHall.ConcertHall");
				break;

			case REVERB_Cave:
				ReverbAssetName = TEXT("/Engine/EngineSounds/ReverbSettings/Cave.Cave");
				break;

			case REVERB_Hallway:
				ReverbAssetName = TEXT("/Engine/EngineSounds/ReverbSettings/Hallway.Hallway");
				break;

			case REVERB_StoneCorridor:
				ReverbAssetName = TEXT("/Engine/EngineSounds/ReverbSettings/StoneCorridor.StoneCorridor");
				break;

			case REVERB_Alley:
				ReverbAssetName = TEXT("/Engine/EngineSounds/ReverbSettings/Alley.Alley");
				break;

			case REVERB_Forest:
				ReverbAssetName = TEXT("/Engine/EngineSounds/ReverbSettings/Forest.Forest");
				break;

			case REVERB_City:
				ReverbAssetName = TEXT("/Engine/EngineSounds/ReverbSettings/City.City");
				break;

			case REVERB_Mountains:
				ReverbAssetName = TEXT("/Engine/EngineSounds/ReverbSettings/Mountains.Mountains");
				break;

			case REVERB_Quarry:
				ReverbAssetName = TEXT("/Engine/EngineSounds/ReverbSettings/Quarry.Quarry");
				break;

			case REVERB_Plain:
				ReverbAssetName = TEXT("/Engine/EngineSounds/ReverbSettings/Plain.Plain");
				break;

			case REVERB_ParkingLot:
				ReverbAssetName = TEXT("/Engine/EngineSounds/ReverbSettings/ParkingLot.ParkingLot");
				break;

			case REVERB_SewerPipe:
				ReverbAssetName = TEXT("/Engine/EngineSounds/ReverbSettings/SewerPipe.SewerPipe");
				break;

			case REVERB_Underwater:
				ReverbAssetName = TEXT("/Engine/EngineSounds/ReverbSettings/Underwater.Underwater");
				break;

			case REVERB_SmallRoom:
				ReverbAssetName = TEXT("/Engine/EngineSounds/ReverbSettings/SmallRoom.SmallRoom");
				break;

			case REVERB_MediumRoom:
				ReverbAssetName = TEXT("/Engine/EngineSounds/ReverbSettings/MediumRoom.MediumRoom");
				break;

			case REVERB_LargeRoom:
				ReverbAssetName = TEXT("/Engine/EngineSounds/ReverbSettings/LargeRoom.LargeRoom");
				break;

			case REVERB_MediumHall:
				ReverbAssetName = TEXT("/Engine/EngineSounds/ReverbSettings/MediumHall.MediumHall");
				break;

			case REVERB_LargeHall:
				ReverbAssetName = TEXT("/Engine/EngineSounds/ReverbSettings/LargeHall.LargeHall");
				break;

			case REVERB_Plate:
				ReverbAssetName = TEXT("/Engine/EngineSounds/ReverbSettings/Plate.Plate");
				break;

			default:
				// This should cover every type of reverb preset
				checkNoEntry();
				break;
		}

		ReverbEffect = LoadObject<UReverbEffect>(NULL, *ReverbAssetName);
		check( ReverbEffect );
	}
}
예제 #29
0
void UModel::Serialize( FArchive& Ar )
{
	Super::Serialize( Ar );

	const int32 StripVertexBufferFlag = 1;
	FStripDataFlags StripFlags( Ar, GetOuter() && GetOuter()->IsA(ABrush::StaticClass()) ? StripVertexBufferFlag : FStripDataFlags::None );

	Ar << Bounds;

	Vectors.BulkSerialize( Ar );
	Points.BulkSerialize( Ar );
	Nodes.BulkSerialize( Ar );
	if( Ar.IsLoading() )
	{
		for( int32 NodeIndex=0; NodeIndex<Nodes.Num(); NodeIndex++ )
		{
			Nodes[NodeIndex].NodeFlags &= ~(NF_IsNew|NF_IsFront|NF_IsBack);
		}
	}
	Ar << Surfs;
	Verts.BulkSerialize( Ar );

	if( Ar.IsLoading() && Ar.UE4Ver() < VER_UE4_REMOVE_ZONES_FROM_MODEL)
	{
		int32 NumZones;
		Ar << NumSharedSides << NumZones;

		FZoneProperties DummyZones[FBspNode::MAX_ZONES];
		for( int32 i=0; i<NumZones; i++ )
		{
			Ar << DummyZones[i];
		}
	}
	else
	{
		Ar << NumSharedSides;
	}

#if WITH_EDITOR
	Ar << Polys;
	LeafHulls.BulkSerialize( Ar );
	Leaves.BulkSerialize( Ar );
#else
	if(Ar.IsLoading())
	{
		UPolys* DummyPolys;
		Ar << DummyPolys;

		TArray<int32> DummyLeafHulls;
		DummyLeafHulls.BulkSerialize( Ar );

		TArray<FLeaf> DummyLeaves;
		DummyLeaves.BulkSerialize( Ar );
	}
#endif

	Ar << RootOutside << Linked;

	if(Ar.IsLoading() && Ar.UE4Ver() < VER_UE4_REMOVE_ZONES_FROM_MODEL)
	{
		TArray<int32> DummyPortalNodes;
		DummyPortalNodes.BulkSerialize( Ar );
	}

	Ar << NumUniqueVertices; 
	// load/save vertex buffer
	if( StripFlags.IsEditorDataStripped() == false || StripFlags.IsClassDataStripped( StripVertexBufferFlag ) == false )
	{
		Ar << VertexBuffer;
	}

#if WITH_EDITOR
	if(GIsEditor)
	{
		CalculateUniqueVertCount();
	}
#endif // WITH_EDITOR

	// serialize the lighting guid if it's there
	Ar << LightingGuid;

	Ar << LightmassSettings;
}
예제 #30
0
void UBlueprint::Serialize(FArchive& Ar)
{
	Super::Serialize(Ar);

#if WITH_EDITORONLY_DATA
	if(Ar.IsLoading() && Ar.UE4Ver() < VER_UE4_BLUEPRINT_VARS_NOT_READ_ONLY)
	{
		// Allow all blueprint defined vars to be read/write.  undoes previous convention of making exposed variables read-only
		for (int32 i = 0; i < NewVariables.Num(); ++i)
		{
			FBPVariableDescription& Variable = NewVariables[i];
			Variable.PropertyFlags &= ~CPF_BlueprintReadOnly;
		}
	}

	if(Ar.IsLoading() && Ar.UE4Ver() < VER_UE4_ADD_KISMETVISIBLE)
	{
		for (int32 i = 0; i < NewVariables.Num(); ++i)
		{
			FBPVariableDescription& Variable = NewVariables[i];
			Variable.PropertyFlags |= CPF_BlueprintVisible;
		}
	}

	if (Ar.UE4Ver() < VER_UE4_K2NODE_REFERENCEGUIDS)
	{
		for (int32 Index = 0; Index < NewVariables.Num(); ++Index)
		{
			NewVariables[Index].VarGuid = FGuid::NewGuid();
		}
	}

	// Preload our parent blueprints
	if (Ar.IsLoading())
	{
		for (UClass* ClassIt = ParentClass; (ClassIt != NULL) && !(ClassIt->HasAnyClassFlags(CLASS_Native)); ClassIt = ClassIt->GetSuperClass())
		{
			if (ClassIt->ClassGeneratedBy->HasAnyFlags(RF_NeedLoad))
			{
				ClassIt->ClassGeneratedBy->GetLinker()->Preload(ClassIt->ClassGeneratedBy);
			}
		}
	}

	// If we don't have a skeleton class via compile-on-load, generate one now
	if( Ar.IsLoading() && (SkeletonGeneratedClass == NULL) )
	{
		bool bWasRegen = bIsRegeneratingOnLoad;
		bIsRegeneratingOnLoad = true;

		FBlueprintEditorUtils::PreloadMembers(this);
		FBlueprintEditorUtils::PreloadConstructionScript(this);
		FKismetEditorUtilities::GenerateBlueprintSkeleton(this);

		bIsRegeneratingOnLoad = bWasRegen;
	}

	if (Ar.UE4Ver() < VER_UE4_BP_ACTOR_VARIABLE_DEFAULT_PREVENTING)
	{
		// Actor variables can't have default values (because Blueprint templates are library elements that can 
		// bridge multiple levels and different levels might not have the actor that the default is referencing).
		for (int32 i = 0; i < NewVariables.Num(); ++i)
		{
			FBPVariableDescription& Variable = NewVariables[i];

			const FEdGraphPinType& VarType = Variable.VarType;
			if (!VarType.PinSubCategoryObject.IsValid()) // ignore variables that don't have associated objects
			{
				continue;
			}

			const UClass* ClassObject = Cast<UClass>(VarType.PinSubCategoryObject.Get());
			// if the object type is an actor...
			if ((ClassObject == NULL) && ClassObject->IsChildOf(AActor::StaticClass()))
			{
				// hide the default value field
				Variable.PropertyFlags |= CPF_DisableEditOnTemplate;
			}
		}
	}
#endif // WITH_EDITORONLY_DATA
}