void USplineComponent::Serialize(FArchive& Ar) { Super::Serialize(Ar); // Support old resources which don't have the rotation and scale splines present const int32 ArchiveUE4Version = Ar.UE4Ver(); if (ArchiveUE4Version < VER_UE4_INTERPCURVE_SUPPORTS_LOOPING) { int32 NumPoints = SplineInfo.Points.Num(); // The start point is no longer cloned as the endpoint when the spline is looped, so remove the extra endpoint if present const bool bHasExtraEndpoint = bClosedLoop && (SplineInfo.Points[0].OutVal == SplineInfo.Points[NumPoints - 1].OutVal); if (bHasExtraEndpoint) { SplineInfo.Points.RemoveAt(NumPoints - 1, 1, false); NumPoints--; } // Fill the other two splines with some defaults SplineRotInfo.Points.Reset(NumPoints); SplineScaleInfo.Points.Reset(NumPoints); for (int32 Count = 0; Count < NumPoints; Count++) { SplineRotInfo.Points.Emplace(0.0f, FQuat::Identity, FQuat::Identity, FQuat::Identity, CIM_CurveAuto); SplineScaleInfo.Points.Emplace(0.0f, FVector(1.0f), FVector::ZeroVector, FVector::ZeroVector, CIM_CurveAuto); } USplineComponent* Archetype = CastChecked<USplineComponent>(GetArchetype()); bSplineHasBeenEdited = (SplineInfo.Points != Archetype->SplineInfo.Points); UpdateSpline(); } }
AAFCueActor::AAFCueActor(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) { PrimaryActorTick.bCanEverTick = true; PrimaryActorTick.bStartWithTickEnabled = true; StartTime = 0; EndTime = 5; if (HasAnyFlags(RF_ClassDefaultObject) || GetArchetype() == GetDefault<AAFCueActor>()) { Sequence = ObjectInitializer.CreateDefaultSubobject<UGAEffectCueSequence>(this, "Sequence"); Sequence->SetFlags(RF_Public | RF_Transactional); SequencePlayer = ObjectInitializer.CreateDefaultSubobject<UActorSequencePlayer>(this, "SequencePlayer"); } }
void UChildActorComponent::PostEditChangeChainProperty(FPropertyChangedChainEvent& PropertyChangedEvent) { if (PropertyChangedEvent.Property && PropertyChangedEvent.Property->GetFName() == GET_MEMBER_NAME_CHECKED(UChildActorComponent, ChildActorClass)) { if (IsTemplate()) { if (ChildActorClass) { if (ChildActorTemplate == nullptr || (ChildActorTemplate->GetClass() != ChildActorClass)) { Modify(); AActor* NewChildActorTemplate = NewObject<AActor>(GetTransientPackage(), ChildActorClass, NAME_None, RF_ArchetypeObject | RF_Transactional | RF_Public); if (ChildActorTemplate) { UEngine::CopyPropertiesForUnrelatedObjects(ChildActorTemplate, NewChildActorTemplate); ChildActorTemplate->Rename(nullptr, GetTransientPackage(), REN_DontCreateRedirectors); } ChildActorTemplate = NewChildActorTemplate; // Record initial object state in case we're in a transaction context. ChildActorTemplate->Modify(); // Now set the actual name and outer to the BPGC. const FString TemplateName = FString::Printf(TEXT("%s_%s_CAT"), *GetName(), *ChildActorClass->GetName()); ChildActorTemplate->Rename(*TemplateName, this, REN_DoNotDirty | REN_DontCreateRedirectors | REN_ForceNoResetLoaders); } } else if (ChildActorTemplate) { Modify(); ChildActorTemplate->Rename(nullptr, GetTransientPackage(), REN_DontCreateRedirectors); ChildActorTemplate = nullptr; } } else { ChildActorTemplate = CastChecked<UChildActorComponent>(GetArchetype())->ChildActorTemplate; } } Super::PostEditChangeChainProperty(PropertyChangedEvent); }
void UActorComponent::DetermineUCSModifiedProperties() { UCSModifiedProperties.Empty(); if (CreationMethod == EComponentCreationMethod::SimpleConstructionScript) { class FComponentPropertySkipper : public FArchive { public: FComponentPropertySkipper() : FArchive() { ArIsSaving = true; } virtual bool ShouldSkipProperty(const UProperty* InProperty) const override { return ( InProperty->HasAnyPropertyFlags(CPF_Transient | CPF_ContainsInstancedReference | CPF_InstancedReference) || !InProperty->HasAnyPropertyFlags(CPF_Edit | CPF_Interp)); } } PropertySkipper; UClass* ComponentClass = GetClass(); UObject* ComponentArchetype = GetArchetype(); for (TFieldIterator<UProperty> It(ComponentClass); It; ++It) { UProperty* Property = *It; if( Property->ShouldSerializeValue(PropertySkipper) ) { for( int32 Idx=0; Idx<Property->ArrayDim; Idx++ ) { uint8* DataPtr = Property->ContainerPtrToValuePtr <uint8>((uint8*)this, Idx); uint8* DefaultValue = Property->ContainerPtrToValuePtrForDefaults<uint8>(ComponentClass, (uint8*)ComponentArchetype, Idx); if (!Property->Identical( DataPtr, DefaultValue)) { UCSModifiedProperties.Add(FSimpleMemberReference()); FMemberReference::FillSimpleMemberReference<UProperty>(Property, UCSModifiedProperties.Last()); break; } } } } } }
void UChildActorComponent::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) { if (PropertyChangedEvent.Property && PropertyChangedEvent.Property->GetFName() == GET_MEMBER_NAME_CHECKED(UChildActorComponent, ChildActorClass)) { ChildActorName = NAME_None; if (!IsTemplate()) { UChildActorComponent* Archetype = CastChecked<UChildActorComponent>(GetArchetype()); ChildActorTemplate = (Archetype->ChildActorClass == ChildActorClass ? Archetype->ChildActorTemplate : nullptr); } // If this was created by construction script, the post edit change super call will destroy it anyways if (!IsCreatedByConstructionScript()) { DestroyChildActor(); CreateChildActor(); } } Super::PostEditChangeProperty(PropertyChangedEvent); }
void FHotReloadClassReinstancer::RecreateCDOAndSetupOldClassReinstancing(UClass* InOldClass) { // Set base class members to valid values ClassToReinstance = InOldClass; DuplicatedClass = InOldClass; OriginalCDO = InOldClass->GetDefaultObject(); bHasReinstanced = false; bSkipGarbageCollection = false; bNeedsReinstancing = false; NewClass = InOldClass; // The class doesn't change in this case // Collect the original property values SerializeCDOProperties(InOldClass->GetDefaultObject(), OriginalCDOProperties); // Remember all the basic info about the object before we rename it EObjectFlags CDOFlags = OriginalCDO->GetFlags(); UObject* CDOOuter = OriginalCDO->GetOuter(); FName CDOName = OriginalCDO->GetFName(); // Rename original CDO, so we can store this one as OverridenArchetypeForCDO // and create new one with the same name and outer. OriginalCDO->Rename( *MakeUniqueObjectName( GetTransientPackage(), OriginalCDO->GetClass(), *FString::Printf(TEXT("BPGC_ARCH_FOR_CDO_%s"), *InOldClass->GetName()) ).ToString(), GetTransientPackage(), REN_DoNotDirty | REN_DontCreateRedirectors | REN_NonTransactional | REN_SkipGeneratedClasses | REN_ForceNoResetLoaders); // Re-create the CDO, re-running its constructor ReconstructClassDefaultObject(InOldClass, CDOOuter, CDOName, CDOFlags); ReconstructedCDOsMap.Add(OriginalCDO, InOldClass->GetDefaultObject()); // Collect the property values after re-constructing the CDO SerializeCDOProperties(InOldClass->GetDefaultObject(), ReconstructedCDOProperties); // We only want to re-instance the old class if its CDO's values have changed or any of its DSOs' property values have changed if (DefaultPropertiesHaveChanged()) { bNeedsReinstancing = true; SaveClassFieldMapping(InOldClass); TArray<UClass*> ChildrenOfClass; GetDerivedClasses(InOldClass, ChildrenOfClass); for (auto ClassIt = ChildrenOfClass.CreateConstIterator(); ClassIt; ++ClassIt) { UClass* ChildClass = *ClassIt; UBlueprint* ChildBP = Cast<UBlueprint>(ChildClass->ClassGeneratedBy); if (ChildBP && !ChildBP->HasAnyFlags(RF_BeingRegenerated)) { if (!ChildBP->HasAnyFlags(RF_NeedLoad)) { Children.AddUnique(ChildBP); auto BPGC = Cast<UBlueprintGeneratedClass>(ChildBP->GeneratedClass); auto CurrentCDO = BPGC ? BPGC->GetDefaultObject(false) : nullptr; if (CurrentCDO && (OriginalCDO == CurrentCDO->GetArchetype())) { BPGC->OverridenArchetypeForCDO = OriginalCDO; } } } } } }