void UActorRecording::StartRecordingNewComponents(ULevelSequence* CurrentSequence, float CurrentSequenceTime) { if (GetActorToRecord() != nullptr) { // find the new component(s) TInlineComponentArray<USceneComponent*> NewComponents; TArray<USceneComponent*> SceneComponents; GetSceneComponents(SceneComponents); for(USceneComponent* SceneComponent : SceneComponents) { if(ValidComponent(SceneComponent)) { TWeakObjectPtr<USceneComponent> WeakSceneComponent(SceneComponent); int32 FoundIndex = TrackedComponents.Find(WeakSceneComponent); if(FoundIndex == INDEX_NONE) { // new component! NewComponents.Add(SceneComponent); } } } ProcessNewComponentArray(NewComponents); UMovieScene* MovieScene = CurrentSequence->GetMovieScene(); check(MovieScene); FAnimationRecordingSettings ComponentAnimationSettings = AnimationSettings; ComponentAnimationSettings.bRemoveRootAnimation = false; ComponentAnimationSettings.bRecordInWorldSpace = false; const USequenceRecorderSettings* Settings = GetDefault<USequenceRecorderSettings>(); if (!bRecordToPossessable) { FMovieSceneSpawnable* Spawnable = MovieScene->FindSpawnable(Guid); check(Spawnable); AActor* ObjectTemplate = CastChecked<AActor>(Spawnable->GetObjectTemplate()); for (USceneComponent* SceneComponent : NewComponents) { // new component, so we need to add this to our BP if it didn't come from SCS FName NewName; if (SceneComponent->CreationMethod != EComponentCreationMethod::SimpleConstructionScript) { // Give this component a unique name within its parent NewName = *FString::Printf(TEXT("Dynamic%s"), *SceneComponent->GetFName().GetPlainNameString()); NewName.SetNumber(1); while (FindObjectFast<UObject>(ObjectTemplate, NewName)) { NewName.SetNumber(NewName.GetNumber() + 1); } USceneComponent* TemplateRoot = ObjectTemplate->GetRootComponent(); USceneComponent* AttachToComponent = nullptr; // look for a similar attach parent in the current structure USceneComponent* AttachParent = SceneComponent->GetAttachParent(); if(AttachParent != nullptr) { // First off, check if we're attached to a component that has already been duplicated into this object // If so, the name lookup will fail, so we use a direct reference if (TWeakObjectPtr<USceneComponent>* DuplicatedComponent = DuplicatedDynamicComponents.Find(AttachParent)) { AttachToComponent = DuplicatedComponent->Get(); } // If we don't have an attachment parent duplicated already, perform a name lookup if (!AttachToComponent) { FName AttachName = SceneComponent->GetAttachParent()->GetFName(); TInlineComponentArray<USceneComponent*> AllChildren; ObjectTemplate->GetComponents(AllChildren); for (USceneComponent* Child : AllChildren) { CA_SUPPRESS(28182); // Dereferencing NULL pointer. 'Child' contains the same NULL value as 'AttachToComponent' did. if (Child->GetFName() == AttachName) { AttachToComponent = Child; break; } } } } if (!AttachToComponent) { AttachToComponent = ObjectTemplate->GetRootComponent(); } USceneComponent* NewTemplateComponent = Cast<USceneComponent>(StaticDuplicateObject(SceneComponent, ObjectTemplate, NewName, RF_AllFlags & ~RF_Transient)); NewTemplateComponent->AttachToComponent(AttachToComponent, FAttachmentTransformRules::KeepRelativeTransform, SceneComponent->GetAttachSocketName()); ObjectTemplate->AddInstanceComponent(NewTemplateComponent); DuplicatedDynamicComponents.Add(SceneComponent, NewTemplateComponent); } else { NewName = SceneComponent->GetFName(); } StartRecordingComponentProperties(NewName, SceneComponent, GetActorToRecord(), CurrentSequence, CurrentSequenceTime, ComponentAnimationSettings); bNewComponentAddedWhileRecording = true; } SyncTrackedComponents(); } else { for (USceneComponent* SceneComponent : NewComponents) { // new component, start recording StartRecordingComponentProperties(SceneComponent->GetFName(), SceneComponent, GetActorToRecord(), CurrentSequence, CurrentSequenceTime, ComponentAnimationSettings); } SyncTrackedComponents(); } } }
void UChildActorComponent::OnRegister() { Super::OnRegister(); if (ChildActor) { if (ChildActor->GetClass() != ChildActorClass) { DestroyChildActor(); CreateChildActor(); } else { ChildActorName = ChildActor->GetFName(); USceneComponent* ChildRoot = ChildActor->GetRootComponent(); if (ChildRoot && ChildRoot->GetAttachParent() != this) { // attach new actor to this component // we can't attach in CreateChildActor since it has intermediate Mobility set up // causing spam with inconsistent mobility set up // so moving Attach to happen in Register ChildRoot->AttachToComponent(this, FAttachmentTransformRules::SnapToTargetNotIncludingScale); } // Ensure the components replication is correctly initialized SetIsReplicated(ChildActor->GetIsReplicated()); } } else if (ChildActorClass) { CreateChildActor(); } }
UActorComponent* UActorBlueprintLibrary::AttachComponentOfClass(UObject* WorldContextObject, TSubclassOf<UActorComponent> ComponentClass, AActor* Owner, FName ComponentName, USceneComponent* AttachTo, FName SocketName) { if (!Owner) { return nullptr; } UActorComponent* Component = NewObject<UActorComponent>(Owner, *ComponentClass, ComponentName); if (!Component) { return nullptr; } Component->RegisterComponent(); Component->OnComponentCreated(); USceneComponent* SceneComponent = Cast<USceneComponent>(Component); if (SceneComponent) { SceneComponent->SetWorldLocation(Owner->GetActorLocation()); SceneComponent->SetWorldRotation(Owner->GetActorRotation()); USceneComponent* AttachToComponent = AttachTo ? AttachTo : Owner->GetRootComponent(); SceneComponent->AttachToComponent(AttachToComponent, FAttachmentTransformRules::KeepWorldTransform, SocketName); } return Component; }
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(); } } } } } }