UActorComponent* AActor::AddComponent(FName TemplateName, bool bManualAttachment, const FTransform& RelativeTransform, const UObject* ComponentTemplateContext) { UActorComponent* Template = nullptr; UBlueprintGeneratedClass* BlueprintGeneratedClass = Cast<UBlueprintGeneratedClass>((ComponentTemplateContext != nullptr) ? ComponentTemplateContext->GetClass() : GetClass()); while(BlueprintGeneratedClass != nullptr) { Template = BlueprintGeneratedClass->FindComponentTemplateByName(TemplateName); if(nullptr != Template) { break; } BlueprintGeneratedClass = Cast<UBlueprintGeneratedClass>(BlueprintGeneratedClass->GetSuperClass()); } bool bIsSceneComponent = false; UActorComponent* NewActorComp = CreateComponentFromTemplate(Template); if(NewActorComp != nullptr) { // Call function to notify component it has been created NewActorComp->OnComponentCreated(); // The user has the option of doing attachment manually where they have complete control or via the automatic rule // that the first component added becomes the root component, with subsequent components attached to the root. USceneComponent* NewSceneComp = Cast<USceneComponent>(NewActorComp); if(NewSceneComp != nullptr) { if (!bManualAttachment) { if (RootComponent == nullptr) { RootComponent = NewSceneComp; } else { NewSceneComp->AttachTo(RootComponent); } } NewSceneComp->SetRelativeTransform(RelativeTransform); bIsSceneComponent = true; } // Register component, which will create physics/rendering state, now component is in correct position NewActorComp->RegisterComponent(); UWorld* World = GetWorld(); if (!bRunningUserConstructionScript && World && bIsSceneComponent) { UPrimitiveComponent* NewPrimitiveComponent = Cast<UPrimitiveComponent>(NewActorComp); if (NewPrimitiveComponent && ACullDistanceVolume::CanBeAffectedByVolumes(NewPrimitiveComponent)) { World->UpdateCullDistanceVolumes(this, NewPrimitiveComponent); } } } return NewActorComp; }
void UChildActorComponent::ApplyComponentInstanceData(FChildActorComponentInstanceData* ChildActorInstanceData, const ECacheApplyPhase CacheApplyPhase) { check(ChildActorInstanceData); ChildActorName = ChildActorInstanceData->ChildActorName; if (ChildActor) { // Only rename if it is safe to if(ChildActorName != NAME_None) { const FString ChildActorNameString = ChildActorName.ToString(); if (ChildActor->Rename(*ChildActorNameString, nullptr, REN_Test)) { ChildActor->Rename(*ChildActorNameString, nullptr, REN_DoNotDirty | (IsLoading() ? REN_ForceNoResetLoaders : REN_None)); } } if (ChildActorInstanceData->ComponentInstanceData) { ChildActorInstanceData->ComponentInstanceData->ApplyToActor(ChildActor, CacheApplyPhase); } USceneComponent* ChildActorRoot = ChildActor->GetRootComponent(); if (ChildActorRoot) { for (const auto& AttachInfo : ChildActorInstanceData->AttachedActors) { AActor* AttachedActor = AttachInfo.Actor.Get(); if (AttachedActor) { USceneComponent* AttachedRootComponent = AttachedActor->GetRootComponent(); if (AttachedRootComponent) { AttachedActor->DetachRootComponentFromParent(); AttachedRootComponent->AttachToComponent(ChildActorRoot, FAttachmentTransformRules::KeepWorldTransform, AttachInfo.SocketName); AttachedRootComponent->SetRelativeTransform(AttachInfo.RelativeTransform); AttachedRootComponent->UpdateComponentToWorld(); } } } } } }
void FMovieScene3DConstraintTrackInstance::RestoreState(const TArray<UObject*>& RuntimeObjects, IMovieScenePlayer& Player, FMovieSceneSequenceInstance& SequenceInstance) { for (int32 ObjIndex = 0; ObjIndex < RuntimeObjects.Num(); ++ObjIndex) { if (!IsValid(RuntimeObjects[ObjIndex])) { continue; } USceneComponent* SceneComponent = MovieSceneHelpers::SceneComponentFromRuntimeObject(RuntimeObjects[ObjIndex]); if (SceneComponent != nullptr) { FTransform *Transform = InitTransformMap.Find(RuntimeObjects[ObjIndex]); if (Transform != nullptr) { SceneComponent->SetRelativeTransform(*Transform); } } } }
void UChildActorComponent::ApplyComponentInstanceData(FChildActorComponentInstanceData* ChildActorInstanceData) { check(ChildActorInstanceData); ChildActorName = ChildActorInstanceData->ChildActorName; if (ChildActor) { // Only rename if it is safe to if(ChildActorName != NAME_None) { const FString ChildActorNameString = ChildActorName.ToString(); if (ChildActor->Rename(*ChildActorNameString, nullptr, REN_Test)) { ChildActor->Rename(*ChildActorNameString, nullptr, REN_DoNotDirty); } } USceneComponent* ChildActorRoot = ChildActor->GetRootComponent(); if (ChildActorRoot) { for (const auto& AttachInfo : ChildActorInstanceData->AttachedActors) { AActor* AttachedActor = AttachInfo.Actor.Get(); if (AttachedActor) { USceneComponent* AttachedRootComponent = AttachedActor->GetRootComponent(); if (AttachedRootComponent) { AttachedActor->DetachRootComponentFromParent(); AttachedRootComponent->AttachTo(ChildActorRoot, AttachInfo.SocketName, EAttachLocation::KeepWorldPosition); AttachedRootComponent->SetRelativeTransform(AttachInfo.RelativeTransform); AttachedRootComponent->UpdateComponentToWorld(); } } } } } }
void FPreviewScene::AddComponent(UActorComponent* Component,const FTransform& LocalToWorld) { Components.AddUnique(Component); USceneComponent* SceneComp = Cast<USceneComponent>(Component); if(SceneComp && SceneComp->GetAttachParent() == NULL) { SceneComp->SetRelativeTransform(LocalToWorld); } Component->RegisterComponentWithWorld(GetWorld()); if (bForceAllUsedMipsResident) { // Add a mip streaming override to the new mesh UMeshComponent* pMesh = Cast<UMeshComponent>(Component); if (pMesh != NULL) { pMesh->SetTextureForceResidentFlag(true); } } GetScene()->UpdateSpeedTreeWind(0.0); }
void AActor::RerunConstructionScripts() { checkf(!HasAnyFlags(RF_ClassDefaultObject), TEXT("RerunConstructionScripts should never be called on a CDO as it can mutate the transient data on the CDO which then propagates to instances!")); FEditorScriptExecutionGuard ScriptGuard; // don't allow (re)running construction scripts on dying actors bool bAllowReconstruction = !IsPendingKill() && !HasAnyFlags(RF_BeginDestroyed|RF_FinishDestroyed); #if WITH_EDITOR if(bAllowReconstruction && GIsEditor) { // Generate the blueprint hierarchy for this actor TArray<UBlueprint*> ParentBPStack; bAllowReconstruction = UBlueprint::GetBlueprintHierarchyFromClass(GetClass(), ParentBPStack); if(bAllowReconstruction) { for(int i = ParentBPStack.Num() - 1; i > 0 && bAllowReconstruction; --i) { const UBlueprint* ParentBP = ParentBPStack[i]; if(ParentBP && ParentBP->bBeingCompiled) { // don't allow (re)running construction scripts if a parent BP is being compiled bAllowReconstruction = false; } } } } #endif if(bAllowReconstruction) { // Set global flag to let system know we are reconstructing blueprint instances TGuardValue<bool> GuardTemplateNameFlag(GIsReconstructingBlueprintInstances, true); // Temporarily suspend the undo buffer; we don't need to record reconstructed component objects into the current transaction ITransaction* CurrentTransaction = GUndo; GUndo = NULL; // Create cache to store component data across rerunning construction scripts #if WITH_EDITOR FActorTransactionAnnotation* ActorTransactionAnnotation = CurrentTransactionAnnotation.Get(); #endif FComponentInstanceDataCache* InstanceDataCache; FTransform OldTransform = FTransform::Identity; FName SocketName; AActor* Parent = NULL; USceneComponent* ParentComponent = NULL; bool bUseRootComponentProperties = true; // Struct to store info about attached actors struct FAttachedActorInfo { AActor* AttachedActor; FName AttachedToSocket; bool bSetRelativeTransform; FTransform RelativeTransform; }; // Save info about attached actors TArray<FAttachedActorInfo> AttachedActorInfos; #if WITH_EDITOR if (ActorTransactionAnnotation) { InstanceDataCache = &ActorTransactionAnnotation->ComponentInstanceData; if (ActorTransactionAnnotation->bRootComponentDataCached) { OldTransform = ActorTransactionAnnotation->RootComponentData.Transform; Parent = ActorTransactionAnnotation->RootComponentData.AttachedParentInfo.Actor.Get(); if (Parent) { USceneComponent* AttachParent = ActorTransactionAnnotation->RootComponentData.AttachedParentInfo.AttachParent.Get(); ParentComponent = (AttachParent ? AttachParent : FindObjectFast<USceneComponent>(Parent, ActorTransactionAnnotation->RootComponentData.AttachedParentInfo.AttachParentName)); SocketName = ActorTransactionAnnotation->RootComponentData.AttachedParentInfo.SocketName; DetachRootComponentFromParent(); } for (const auto& CachedAttachInfo : ActorTransactionAnnotation->RootComponentData.AttachedToInfo) { AActor* AttachedActor = CachedAttachInfo.Actor.Get(); if (AttachedActor) { FAttachedActorInfo Info; Info.AttachedActor = AttachedActor; Info.AttachedToSocket = CachedAttachInfo.SocketName; Info.bSetRelativeTransform = true; Info.RelativeTransform = CachedAttachInfo.RelativeTransform; AttachedActorInfos.Add(Info); AttachedActor->DetachRootComponentFromParent(); } } bUseRootComponentProperties = false; } } else #endif { InstanceDataCache = new FComponentInstanceDataCache(this); // If there are attached objects detach them and store the socket names TArray<AActor*> AttachedActors; GetAttachedActors(AttachedActors); for (AActor* AttachedActor : AttachedActors) { USceneComponent* EachRoot = AttachedActor->GetRootComponent(); // If the component we are attached to is about to go away... if (EachRoot && EachRoot->AttachParent && EachRoot->AttachParent->IsCreatedByConstructionScript()) { // Save info about actor to reattach FAttachedActorInfo Info; Info.AttachedActor = AttachedActor; Info.AttachedToSocket = EachRoot->AttachSocketName; Info.bSetRelativeTransform = false; AttachedActorInfos.Add(Info); // Now detach it AttachedActor->Modify(); EachRoot->DetachFromParent(true); } } } if (bUseRootComponentProperties && RootComponent != nullptr) { // Do not need to detach if root component is not going away if (RootComponent->AttachParent != NULL && RootComponent->IsCreatedByConstructionScript()) { Parent = RootComponent->AttachParent->GetOwner(); // Root component should never be attached to another component in the same actor! if (Parent == this) { UE_LOG(LogActor, Warning, TEXT("RerunConstructionScripts: RootComponent (%s) attached to another component in this Actor (%s)."), *RootComponent->GetPathName(), *Parent->GetPathName()); Parent = NULL; } ParentComponent = RootComponent->AttachParent; SocketName = RootComponent->AttachSocketName; //detach it to remove any scaling RootComponent->DetachFromParent(true); } OldTransform = RootComponent->ComponentToWorld; OldTransform.SetTranslation(RootComponent->GetComponentLocation()); // take into account any custom location } #if WITH_EDITOR // Save the current construction script-created components by name TMap<const FName, UObject*> DestroyedComponentsByName; TInlineComponentArray<UActorComponent*> PreviouslyAttachedComponents; GetComponents(PreviouslyAttachedComponents); for (auto Component : PreviouslyAttachedComponents) { if (Component) { if (Component->IsCreatedByConstructionScript()) { DestroyedComponentsByName.Add(Component->GetFName(), Component); } else { UActorComponent* OuterComponent = Component->GetTypedOuter<UActorComponent>(); while (OuterComponent) { if (OuterComponent->IsCreatedByConstructionScript()) { DestroyedComponentsByName.Add(Component->GetFName(), Component); break; } OuterComponent = OuterComponent->GetTypedOuter<UActorComponent>(); } } } } #endif // Destroy existing components DestroyConstructedComponents(); // Reset random streams ResetPropertiesForConstruction(); // Exchange net roles before running construction scripts UWorld *OwningWorld = GetWorld(); if (OwningWorld && !OwningWorld->IsServer()) { ExchangeNetRoles(true); } // Run the construction scripts ExecuteConstruction(OldTransform, InstanceDataCache); if(Parent) { USceneComponent* ChildRoot = GetRootComponent(); if (ParentComponent == NULL) { ParentComponent = Parent->GetRootComponent(); } if (ChildRoot != NULL && ParentComponent != NULL) { ChildRoot->AttachTo(ParentComponent, SocketName, EAttachLocation::KeepWorldPosition); } } // If we had attached children reattach them now - unless they are already attached for(FAttachedActorInfo& Info : AttachedActorInfos) { // If this actor is no longer attached to anything, reattach if (!Info.AttachedActor->IsPendingKill() && Info.AttachedActor->GetAttachParentActor() == NULL) { USceneComponent* ChildRoot = Info.AttachedActor->GetRootComponent(); if (ChildRoot && ChildRoot->AttachParent != RootComponent) { ChildRoot->AttachTo(RootComponent, Info.AttachedToSocket, EAttachLocation::KeepWorldPosition); if (Info.bSetRelativeTransform) { ChildRoot->SetRelativeTransform(Info.RelativeTransform); } ChildRoot->UpdateComponentToWorld(); } } } // Restore the undo buffer GUndo = CurrentTransaction; #if WITH_EDITOR // Create the mapping of old->new components and notify the editor of the replacements TMap<UObject*, UObject*> OldToNewComponentMapping; TInlineComponentArray<UActorComponent*> NewComponents; GetComponents(NewComponents); for (auto NewComp : NewComponents) { const FName NewCompName = NewComp->GetFName(); if (DestroyedComponentsByName.Contains(NewCompName)) { OldToNewComponentMapping.Add(DestroyedComponentsByName[NewCompName], NewComp); } } if (GEditor && (OldToNewComponentMapping.Num() > 0)) { GEditor->NotifyToolsOfObjectReplacement(OldToNewComponentMapping); } if (ActorTransactionAnnotation) { CurrentTransactionAnnotation = NULL; } else #endif { delete InstanceDataCache; } } }
UActorComponent* AActor::AddComponent(FName TemplateName, bool bManualAttachment, const FTransform& RelativeTransform, const UObject* ComponentTemplateContext) { UActorComponent* Template = NULL; UBlueprintGeneratedClass* BlueprintGeneratedClass = Cast<UBlueprintGeneratedClass>((ComponentTemplateContext != NULL) ? ComponentTemplateContext->GetClass() : GetClass()); while(BlueprintGeneratedClass != NULL) { Template = BlueprintGeneratedClass->FindComponentTemplateByName(TemplateName); if(NULL != Template) { break; } BlueprintGeneratedClass = Cast<UBlueprintGeneratedClass>(BlueprintGeneratedClass->GetSuperClass()); } UActorComponent* NewActorComp = CreateComponentFromTemplate(Template); if(NewActorComp != NULL) { // The user has the option of doing attachment manually where they have complete control or via the automatic rule // that the first component added becomes the root component, with subsequent components attached to the root. USceneComponent* NewSceneComp = Cast<USceneComponent>(NewActorComp); bool bDeferRegisterStaticComponent = false; EComponentMobility::Type OriginalMobility = EComponentMobility::Movable; if(NewSceneComp != NULL) { // Components with Mobility set to EComponentMobility::Static or EComponentMobility::Stationary can't be properly set up in UCS (all changes will be rejected // due to EComponentMobility::Static flag) so we're going to temporarily change the flag and defer the registration until UCS has finished. bDeferRegisterStaticComponent = bRunningUserConstructionScript && NewSceneComp->Mobility != EComponentMobility::Movable; OriginalMobility = NewSceneComp->Mobility; if (bDeferRegisterStaticComponent) { NewSceneComp->Mobility = EComponentMobility::Movable; } if (!bManualAttachment) { if (RootComponent == NULL) { RootComponent = NewSceneComp; } else { NewSceneComp->AttachTo(RootComponent); } } NewSceneComp->SetRelativeTransform(RelativeTransform); } // Call function to notify component it has been created NewActorComp->OnComponentCreated(); if (bDeferRegisterStaticComponent) { // Defer registration until after UCS has completed. FDeferRegisterStaticComponents::Get().DeferStaticComponent(this, NewSceneComp, OriginalMobility); } else { // Register component, which will create physics/rendering state, now component is in correct position NewActorComp->RegisterComponent(); } } return NewActorComp; }