void FBehaviorTreeDebugger::OnInstanceSelectedInDropdown(UBehaviorTreeComponent* SelectedInstance) { if (SelectedInstance) { ClearDebuggerState(); AController* OldController = TreeInstance.IsValid() ? Cast<AController>(TreeInstance->GetOwner()) : NULL; APawn* OldPawn = OldController != NULL ? OldController->GetPawn() : NULL; USelection* SelectedActors = GEditor->GetSelectedActors(); if (SelectedActors && OldPawn) { SelectedActors->Deselect(OldPawn); } TreeInstance = SelectedInstance; if (SelectedActors && GEditor && SelectedInstance && SelectedInstance->GetOwner()) { AController* TestController = Cast<AController>(SelectedInstance->GetOwner()); APawn* Pawn = TestController != NULL ? TestController->GetPawn() : NULL; if (Pawn) { SelectedActors = GEditor->GetSelectedActors(); SelectedActors->Select(Pawn); AGameplayDebuggingReplicator::OnSelectionChangedDelegate.Broadcast(Pawn); } } Refresh(); } }
void FActorFolders::SetSelectedFolderPath(FName Path) const { // Move the currently selected actors into the new folder USelection* SelectedActors = GEditor->GetSelectedActors(); for (FSelectionIterator SelectionIt(*SelectedActors); SelectionIt; ++SelectionIt) { AActor* Actor = CastChecked<AActor>(*SelectionIt); // If this actor is parented to another, which is also in the selection, skip it so that it moves when its parent does (otherwise it's orphaned) const AActor* ParentActor = Actor->GetAttachParentActor(); if (ParentActor && SelectedActors->IsSelected(ParentActor)) { continue; } // If any child actor isn't being moved with the parent, then orphan them (otherwise they'll end up being forced to move) TArray<AActor*> ChildActors; Actor->GetAttachedActors(ChildActors); for (const auto& ChildActor : ChildActors) { if (ChildActor && !SelectedActors->IsSelected(ChildActor)) { ChildActor->DetachRootComponentFromParent(true); } } Actor->SetFolderPath_Recursively(Path); } }
void UUnrealEdEngine::SetCurrentClass( UClass* InClass ) { USelection* SelectionSet = GetSelectedObjects(); SelectionSet->DeselectAll( UClass::StaticClass() ); if(InClass != NULL) { SelectionSet->Select( InClass ); } }
void UUnrealEdEngine::SelectGroup(AGroupActor* InGroupActor, bool bForceSelection/*=false*/, bool bInSelected/*=true*/, bool bNotify/*=true*/) { USelection* SelectedActors = GetSelectedActors(); SelectedActors->BeginBatchSelectOperation(); SelectedActors->Modify(); static bool bIteratingGroups = false; if( !bIteratingGroups ) { bIteratingGroups = true; // Select all actors within the group (if locked or forced) if( bForceSelection || InGroupActor->IsLocked() ) { TArray<AActor*> GroupActors; InGroupActor->GetGroupActors(GroupActors); for( int32 ActorIndex=0; ActorIndex < GroupActors.Num(); ++ActorIndex ) { SelectActor(GroupActors[ActorIndex], bInSelected, false ); } bForceSelection = true; // Recursively select any subgroups TArray<AGroupActor*> SubGroups; InGroupActor->GetSubGroups(SubGroups); for( int32 GroupIndex=0; GroupIndex < SubGroups.Num(); ++GroupIndex ) { SelectGroup(SubGroups[GroupIndex], bForceSelection, bInSelected, false); } } SelectedActors->EndBatchSelectOperation(bNotify); if (bNotify) { NoteSelectionChange(); } //whenever selection changes, recompute whether the selection contains a locked actor bCheckForLockActors = true; //whenever selection changes, recompute whether the selection contains a world info actor bCheckForWorldSettingsActors = true; bIteratingGroups = false; } }
/** * Attempt to lock/unlock the level of this window * * @param bLocked If true, attempt to lock the level; If false, attempt to unlock the level */ void FLevelViewModel::SetLocked(bool bLocked) { if( !Level.IsValid() ) { return; } // Do nothing if attempting to set the level to the same locked state or if trying to lock/unlock the p-level if ( bLocked == IsLocked() || IsPersistent() ) { return; } // If locking the level, deselect all of its actors and BSP surfaces if ( bLocked ) { USelection* SelectedActors = GEditor->GetSelectedActors(); SelectedActors->Modify(); // Deselect all level actors for ( TArray<AActor*>::TConstIterator LevelActorIterator( Level->Actors ); LevelActorIterator; ++LevelActorIterator ) { AActor* CurActor = *LevelActorIterator; if ( CurActor ) { SelectedActors->Deselect( CurActor ); } } // Deselect all level BSP surfaces EditorLevelUtils::DeselectAllSurfacesInLevel(Level.Get()); // Tell the editor selection status was changed. GEditor->NoteSelectionChange(); // If locking the current level, reset the p-level as the current level //@todo: fix this! } // Change the level's locked status FLevelUtils::ToggleLevelLock( Level.Get() ); }
void FSequencer::SetKey() { USelection* CurrentSelection = GEditor->GetSelectedActors(); TArray<UObject*> SelectedActors; CurrentSelection->GetSelectedObjects( AActor::StaticClass(), SelectedActors ); for (TArray<UObject*>::TIterator It(SelectedActors); It; ++It) { // @todo Handle case of actors which aren't in sequencer yet FGuid ObjectGuid = GetHandleToObject(*It); for ( auto& TrackEditor : TrackEditors ) { // @todo Handle this director track business better if (TrackEditor != DirectorTrackEditor.Pin()) { TrackEditor->AddKey(ObjectGuid); } } } }
void FLevelModel::DeselectAllActors() { ULevel* Level = GetLevelObject(); if (Level == NULL) { return; } USelection* SelectedActors = Editor->GetSelectedActors(); SelectedActors->Modify(); // Deselect all level actors for (auto It = Level->Actors.CreateIterator(); It; ++It) { AActor* CurActor = (*It); if (CurActor) { SelectedActors->Deselect(CurActor); } } }
bool FPhysicsManipulationEdMode::StartTracking( FEditorViewportClient* InViewportClient, FViewport* InViewport ) { //UE_LOG(LogEditorPhysMode, Warning, TEXT("Start Tracking")); FVector GrabLocation(0,0,0); UPrimitiveComponent* ComponentToGrab = NULL; USelection* Selection = GEditor->GetSelectedActors(); for (int32 i=0; i<Selection->Num(); ++i) { AActor* SelectedActor = Cast<AActor>(Selection->GetSelectedObject(i)); if (SelectedActor != NULL) { UPrimitiveComponent* PC = Cast<UPrimitiveComponent>(SelectedActor->GetRootComponent()); if (PC != NULL && PC->BodyInstance.bSimulatePhysics) { ComponentToGrab = PC; HandleTargetLocation = SelectedActor->GetActorLocation(); HandleTargetRotation = SelectedActor->GetActorRotation(); break; } if (ComponentToGrab != NULL) { break; } } } if (ComponentToGrab != NULL) { HandleComp->GrabComponent(ComponentToGrab, NAME_None, ComponentToGrab->GetOwner()->GetActorLocation(), true); } return FEdMode::StartTracking(InViewportClient, InViewport); }
// FNodeSpawnInfo interface virtual void GetActions(UEdGraph* InDestGraph, FVector2D& InOutDestPosition, TArray<UEdGraphNode*>& OutNodes) override { const UBlueprint* Blueprint = FBlueprintEditorUtils::FindBlueprintForGraph(InDestGraph); USelection* SelectedLvlActors = GEditor->GetSelectedActors(); if ((Blueprint != nullptr) && Blueprint->ParentClass->IsChildOf<ALevelScriptActor>() && (SelectedLvlActors->Num() > 0)) { for (FSelectionIterator LvlActorIt(*SelectedLvlActors); LvlActorIt; ++LvlActorIt) { IBlueprintNodeBinder::FBindingSet Bindings; UK2Node_Literal* TemplateRefNode = Cast<UK2Node_Literal>(UBlueprintNodeSpawner::Create(UK2Node_Literal::StaticClass())->Invoke(InDestGraph, Bindings, InOutDestPosition)); TemplateRefNode->SetObjectRef(*LvlActorIt); OutNodes.Add(TemplateRefNode); } } }
FReply FCurveColorCustomization::OnCreateButtonClicked() { if (CurveWidget.IsValid()) { FString DefaultAsset = FPackageName::GetLongPackagePath(Owner->GetOutermost()->GetName()) + TEXT("/") + Owner->GetName() + TEXT("_ExternalCurve"); TSharedRef<SDlgPickAssetPath> NewCurveDlg = SNew(SDlgPickAssetPath) .Title(LOCTEXT("NewCurveDialogTitle", "Choose Location for External Curve Asset")) .DefaultAssetPath(FText::FromString(DefaultAsset)); if (NewCurveDlg->ShowModal() != EAppReturnType::Cancel) { FString Package(NewCurveDlg->GetFullAssetPath().ToString()); FString Name(NewCurveDlg->GetAssetName().ToString()); FString Group(TEXT("")); // Find (or create!) the desired package for this object UPackage* Pkg = CreatePackage(NULL, *Package); UPackage* OutermostPkg = Pkg->GetOutermost(); TArray<UPackage*> TopLevelPackages; TopLevelPackages.Add( OutermostPkg ); if (!PackageTools::HandleFullyLoadingPackages(TopLevelPackages, LOCTEXT("CreateANewObject", "Create a new object"))) { // User aborted. return FReply::Handled(); } if (!PromptUserIfExistingObject(Name, Package, Group, Pkg)) { return FReply::Handled(); } // PromptUserIfExistingObject may have GCed and recreated our outermost package - re-acquire it here. OutermostPkg = Pkg->GetOutermost(); // Create a new asset and set it as the external curve FName AssetName = *Name; UCurveLinearColor* NewCurve = Cast<UCurveLinearColor>(CurveWidget->CreateCurveObject(UCurveLinearColor::StaticClass(), Pkg, AssetName)); if( NewCurve ) { // run through points of editor data and add to external curve for (int32 Index = 0; Index < 4; Index++) { CopyCurveData(&RuntimeCurve->ColorCurves[Index], &NewCurve->FloatCurves[Index]); } // Set the new object as the sole selection. USelection* SelectionSet = GEditor->GetSelectedObjects(); SelectionSet->DeselectAll(); SelectionSet->Select( NewCurve ); // Notify the asset registry FAssetRegistryModule::AssetCreated(NewCurve); // Mark the package dirty... OutermostPkg->MarkPackageDirty(); // Make sure expected type of pointer passed to SetValue, so that it's not interpreted as a bool ExternalCurveHandle->SetValue(NewCurve); } } } return FReply::Handled(); }
void UUnrealEdEngine::SelectNone(bool bNoteSelectionChange, bool bDeselectBSPSurfs, bool WarnAboutManyActors) { if( GEdSelectionLock ) { return; } bool bShowProgress = false; // If there are a lot of actors to process, pop up a warning "are you sure?" box if( WarnAboutManyActors ) { int32 NumSelectedActors = GEditor->GetSelectedActorCount(); if( NumSelectedActors >= EditorActorSelectionDefs::MaxActorsToSelectBeforeWarning ) { bShowProgress = true; const FText ConfirmText = FText::Format( NSLOCTEXT("UnrealEd", "Warning_ManyActorsForDeselect", "There are {0} selected actors. Are you sure you want to deselect them all?" ), FText::AsNumber(NumSelectedActors) ); FSuppressableWarningDialog::FSetupInfo Info( ConfirmText, NSLOCTEXT( "UnrealEd", "Warning_ManyActors", "Warning: Many Actors" ), "Warning_ManyActors" ); Info.ConfirmText = NSLOCTEXT("ModalDialogs", "ManyActorsForDeselectConfirm", "Continue Deselection"); Info.CancelText = NSLOCTEXT("ModalDialogs", "ManyActorsForDeselectCancel", "Keep Current Selection"); FSuppressableWarningDialog ManyActorsWarning( Info ); if( ManyActorsWarning.ShowModal() == FSuppressableWarningDialog::Cancel ) { return; } } } if( bShowProgress ) { GWarn->BeginSlowTask( LOCTEXT("BeginDeselectingActorsTaskMessage", "Deselecting Actors"), true ); } // Make a list of selected actors . . . TArray<AActor*> ActorsToDeselect; for ( FSelectionIterator It( GetSelectedActorIterator() ) ; It ; ++It ) { AActor* Actor = static_cast<AActor*>( *It ); checkSlow( Actor->IsA(AActor::StaticClass()) ); ActorsToDeselect.Add( Actor ); } USelection* SelectedActors = GetSelectedActors(); SelectedActors->BeginBatchSelectOperation(); SelectedActors->Modify(); // . . . and deselect them. for ( int32 ActorIndex = 0 ; ActorIndex < ActorsToDeselect.Num() ; ++ActorIndex ) { AActor* Actor = ActorsToDeselect[ ActorIndex ]; SelectActor( Actor, false, false ); } uint32 NumDeselectSurfaces = 0; UWorld* World = GWorld; if( bDeselectBSPSurfs && World ) { // Unselect all surfaces in all levels. NumDeselectSurfaces += DeselectAllSurfacesForLevel( World->PersistentLevel ); for( int32 LevelIndex = 0 ; LevelIndex < World->StreamingLevels.Num() ; ++LevelIndex ) { ULevelStreaming* StreamingLevel = World->StreamingLevels[LevelIndex]; if( StreamingLevel ) { ULevel* Level = StreamingLevel->GetLoadedLevel(); if ( Level != NULL ) { NumDeselectSurfaces += DeselectAllSurfacesForLevel( Level ); } } } } SelectedActors->EndBatchSelectOperation(bNoteSelectionChange); //prevents clicking on background multiple times spamming selection changes if (ActorsToDeselect.Num() || NumDeselectSurfaces) { GetSelectedActors()->DeselectAll(); if( bNoteSelectionChange ) { NoteSelectionChange(); } //whenever selection changes, recompute whether the selection contains a locked actor bCheckForLockActors = true; //whenever selection changes, recompute whether the selection contains a world info actor bCheckForWorldSettingsActors = true; } if( bShowProgress ) { GWarn->EndSlowTask(); } }
void UUnrealEdEngine::NoteActorMovement() { if( !GUndo && !(GEditor->ClickFlags & CF_MOVE_ACTOR) ) { GEditor->ClickFlags |= CF_MOVE_ACTOR; const FScopedTransaction Transaction( NSLOCTEXT("UnrealEd", "ActorMovement", "Actor Movement") ); GLevelEditorModeTools().Snapping=0; AActor* SelectedActor = NULL; for ( FSelectionIterator It( GetSelectedActorIterator() ) ; It ; ++It ) { AActor* Actor = static_cast<AActor*>( *It ); checkSlow( Actor->IsA(AActor::StaticClass()) ); SelectedActor = Actor; break; } if( SelectedActor == NULL ) { USelection* SelectedActors = GetSelectedActors(); SelectedActors->Modify(); SelectActor( GWorld->GetDefaultBrush(), true, true ); } // Look for an actor that requires snapping. for ( FSelectionIterator It( GetSelectedActorIterator() ) ; It ; ++It ) { AActor* Actor = static_cast<AActor*>( *It ); checkSlow( Actor->IsA(AActor::StaticClass()) ); GLevelEditorModeTools().Snapping = 1; break; } TSet<AGroupActor*> GroupActors; // Modify selected actors. for ( FSelectionIterator It( GetSelectedActorIterator() ) ; It ; ++It ) { AActor* Actor = static_cast<AActor*>( *It ); checkSlow( Actor->IsA(AActor::StaticClass()) ); Actor->Modify(); if (GEditor->bGroupingActive) { // if this actor is in a group, add the GroupActor into a list to be modified shortly AGroupActor* ActorLockedRootGroup = AGroupActor::GetRootForActor(Actor, true); if (ActorLockedRootGroup != nullptr) { GroupActors.Add(ActorLockedRootGroup); } } ABrush* Brush = Cast< ABrush >( Actor ); if ( Brush ) { if( Brush->Brush ) { Brush->Brush->Polys->Element.ModifyAllItems(); } } } // Modify unique group actors for (auto* GroupActor : GroupActors) { GroupActor->Modify(); } } }
void ULiveEditorKismetLibrary::GetAllSelectedEditorObjects( UClass *OfClass, TArray<UObject*> &SelectedObjects ) { USelection *Selection = GEditor->GetSelectedActors(); check(Selection != NULL); Selection->GetSelectedObjects( OfClass, SelectedObjects); }
void FCreateBlueprintFromActorDialog::OnCreateBlueprint(const FString& InAssetPath, bool bInHarvest) { UBlueprint* Blueprint = NULL; if(bInHarvest) { TArray<AActor*> Actors; USelection* SelectedActors = GEditor->GetSelectedActors(); for(FSelectionIterator Iter(*SelectedActors); Iter; ++Iter) { // We only care about actors that are referenced in the world for literals, and also in the same level as this blueprint AActor* Actor = Cast<AActor>(*Iter); if(Actor) { Actors.Add(Actor); } } Blueprint = FKismetEditorUtilities::HarvestBlueprintFromActors(InAssetPath, Actors, true); } else { AActor* ActorToUse = ActorOverride.Get(); if( !ActorToUse ) { TArray< UObject* > SelectedActors; GEditor->GetSelectedActors()->GetSelectedObjects(AActor::StaticClass(), SelectedActors); check(SelectedActors.Num()); ActorToUse = Cast<AActor>(SelectedActors[0]); } const bool bReplaceActor = true; Blueprint = FKismetEditorUtilities::CreateBlueprintFromActor(InAssetPath, ActorToUse, bReplaceActor); } if(Blueprint) { // Rename new instance based on the original actor label rather than the asset name USelection* SelectedActors = GEditor->GetSelectedActors(); if( SelectedActors && SelectedActors->Num() == 1 ) { AActor* Actor = Cast<AActor>(SelectedActors->GetSelectedObject(0)); if(Actor) { FActorLabelUtilities::SetActorLabelUnique(Actor, FPackageName::GetShortName(InAssetPath)); } } // Select the newly created blueprint in the content browser, but don't activate the browser TArray<UObject*> Objects; Objects.Add(Blueprint); GEditor->SyncBrowserToObjects( Objects, false ); } else { FNotificationInfo Info( LOCTEXT("CreateBlueprintFromActorFailed", "Unable to create a blueprint from actor.") ); Info.ExpireDuration = 3.0f; Info.bUseLargeFont = false; TSharedPtr<SNotificationItem> Notification = FSlateNotificationManager::Get().AddNotification(Info); if ( Notification.IsValid() ) { Notification->SetCompletionState( SNotificationItem::CS_Fail ); } } }
FReply SCreateBlueprintFromActorDialog::OnCreateBlueprintFromActorClicked( bool bInHarvest) { ParentWindow->RequestDestroyWindow(); UBlueprint* Blueprint = NULL; if(bInHarvest) { TArray<AActor*> Actors; USelection* SelectedActors = GEditor->GetSelectedActors(); for(FSelectionIterator Iter(*SelectedActors); Iter; ++Iter) { // We only care about actors that are referenced in the world for literals, and also in the same level as this blueprint AActor* Actor = Cast<AActor>(*Iter); if(Actor) { Actors.Add(Actor); } } Blueprint = FKismetEditorUtilities::HarvestBlueprintFromActors(PathForActorBlueprint + TEXT("/") + FileNameWidget.Pin()->GetText().ToString(), Actors, true); } else { TArray< UObject* > SelectedActors; GEditor->GetSelectedActors()->GetSelectedObjects(AActor::StaticClass(), SelectedActors); check(SelectedActors.Num()); Blueprint = FKismetEditorUtilities::CreateBlueprintFromActor(PathForActorBlueprint + TEXT("/") + FileNameWidget.Pin()->GetText().ToString(), (AActor*)SelectedActors[0], true); } if(Blueprint) { // Rename new instance based on the original actor label rather than the asset name USelection* SelectedActors = GEditor->GetSelectedActors(); if( SelectedActors && SelectedActors->Num() == 1 ) { AActor* Actor = Cast<AActor>(SelectedActors->GetSelectedObject(0)); if(Actor) { GEditor->SetActorLabelUnique(Actor, ActorInstanceLabel); } } TArray<UObject*> Objects; Objects.Add(Blueprint); GEditor->SyncBrowserToObjects( Objects ); } else { FNotificationInfo Info( LOCTEXT("CreateBlueprintFromActorFailed", "Unable to create a blueprint from actor.") ); Info.ExpireDuration = 3.0f; Info.bUseLargeFont = false; TSharedPtr<SNotificationItem> Notification = FSlateNotificationManager::Get().AddNotification(Info); if ( Notification.IsValid() ) { Notification->SetCompletionState( SNotificationItem::CS_Fail ); } } return FReply::Handled(); }
void FBlueprintCompileReinstancer::ReplaceInstancesOfClass(UClass* OldClass, UClass* NewClass, UObject* OriginalCDO, TSet<UObject*>* ObjectsThatShouldUseOldStuff) { USelection* SelectedActors; bool bSelectionChanged = false; TArray<UObject*> ObjectsToReplace; const bool bLogConversions = false; // for debugging // Map of old objects to new objects TMap<UObject*, UObject*> OldToNewInstanceMap; TMap<UClass*, UClass*> OldToNewClassMap; OldToNewClassMap.Add(OldClass, NewClass); TMap<FStringAssetReference, UObject*> ReinstancedObjectsWeakReferenceMap; // actors being replace TArray<FActorReplacementHelper> ReplacementActors; // A list of objects (e.g. Blueprints) that potentially have editors open that we need to refresh TArray<UObject*> PotentialEditorsForRefreshing; // A list of component owners that need their construction scripts re-ran (because a component of theirs has been reinstanced) TSet<AActor*> OwnersToReconstruct; // Set global flag to let system know we are reconstructing blueprint instances TGuardValue<bool> GuardTemplateNameFlag(GIsReconstructingBlueprintInstances, true); struct FObjectRemappingHelper { void OnObjectsReplaced(const TMap<UObject*, UObject*>& InReplacedObjects) { ReplacedObjects.Append(InReplacedObjects); } TMap<UObject*, UObject*> ReplacedObjects; } ObjectRemappingHelper; FDelegateHandle OnObjectsReplacedHandle = GEditor->OnObjectsReplaced().AddRaw(&ObjectRemappingHelper,&FObjectRemappingHelper::OnObjectsReplaced); { BP_SCOPED_COMPILER_EVENT_STAT(EKismetReinstancerStats_ReplaceInstancesOfClass); const bool bIncludeDerivedClasses = false; GetObjectsOfClass(OldClass, ObjectsToReplace, bIncludeDerivedClasses); SelectedActors = GEditor->GetSelectedActors(); SelectedActors->BeginBatchSelectOperation(); SelectedActors->Modify(); // Then fix 'real' (non archetype) instances of the class for (UObject* OldObject : ObjectsToReplace) { // Skip non-archetype instances, EXCEPT for component templates const bool bIsComponent = NewClass->IsChildOf(UActorComponent::StaticClass()); if ((!bIsComponent && OldObject->IsTemplate()) || OldObject->IsPendingKill()) { continue; } UBlueprint* CorrespondingBlueprint = Cast<UBlueprint>(OldObject->GetClass()->ClassGeneratedBy); UObject* OldBlueprintDebugObject = nullptr; // If this object is being debugged, cache it off so we can preserve the 'object being debugged' association if ((CorrespondingBlueprint != nullptr) && (CorrespondingBlueprint->GetObjectBeingDebugged() == OldObject)) { OldBlueprintDebugObject = OldObject; } AActor* OldActor = Cast<AActor>(OldObject); UObject* NewUObject = nullptr; // if the object to replace is an actor... if (OldActor != nullptr) { FVector Location = FVector::ZeroVector; FRotator Rotation = FRotator::ZeroRotator; if (USceneComponent* OldRootComponent = OldActor->GetRootComponent()) { Location = OldActor->GetActorLocation(); Rotation = OldActor->GetActorRotation(); } // If this actor was spawned from an Archetype, we spawn the new actor from the new version of that archetype UObject* OldArchetype = OldActor->GetArchetype(); UWorld* World = OldActor->GetWorld(); AActor* NewArchetype = Cast<AActor>(OldToNewInstanceMap.FindRef(OldArchetype)); // Check that either this was an instance of the class directly, or we found a new archetype for it check(OldArchetype == OldClass->GetDefaultObject() || NewArchetype); // Spawn the new actor instance, in the same level as the original, but deferring running the construction script until we have transferred modified properties ULevel* ActorLevel = OldActor->GetLevel(); UClass** MappedClass = OldToNewClassMap.Find(OldActor->GetClass()); UClass* SpawnClass = MappedClass ? *MappedClass : NewClass; FActorSpawnParameters SpawnInfo; SpawnInfo.OverrideLevel = ActorLevel; SpawnInfo.Template = NewArchetype; SpawnInfo.bNoCollisionFail = true; SpawnInfo.bDeferConstruction = true; // Temporarily remove the deprecated flag so we can respawn the Blueprint in the level const bool bIsClassDeprecated = SpawnClass->HasAnyClassFlags(CLASS_Deprecated); SpawnClass->ClassFlags &= ~CLASS_Deprecated; AActor* NewActor = World->SpawnActor(SpawnClass, &Location, &Rotation, SpawnInfo); // Reassign the deprecated flag if it was previously assigned if (bIsClassDeprecated) { SpawnClass->ClassFlags |= CLASS_Deprecated; } check(NewActor != nullptr); NewUObject = NewActor; // store the new actor for the second pass (NOTE: this detaches // OldActor from all child/parent attachments) // // running the NewActor's construction-script is saved for that // second pass (because the construction-script may reference // another instance that hasn't been replaced yet). ReplacementActors.Add(FActorReplacementHelper(NewActor, OldActor)); ReinstancedObjectsWeakReferenceMap.Add(OldObject, NewUObject); OldActor->DestroyConstructedComponents(); // don't want to serialize components from the old actor // Unregister native components so we don't copy any sub-components they generate for themselves (like UCameraComponent does) OldActor->UnregisterAllComponents(); // Unregister any native components, might have cached state based on properties we are going to overwrite NewActor->UnregisterAllComponents(); UEditorEngine::CopyPropertiesForUnrelatedObjects(OldActor, NewActor); // reset properties/streams NewActor->ResetPropertiesForConstruction(); // register native components NewActor->RegisterAllComponents(); // // clean up the old actor (unselect it, remove it from the world, etc.)... if (OldActor->IsSelected()) { GEditor->SelectActor(OldActor, /*bInSelected =*/false, /*bNotify =*/false); bSelectionChanged = true; } if (GEditor->Layers.IsValid()) // ensure(NULL != GEditor->Layers) ?? While cooking the Layers is NULL. { GEditor->Layers->DisassociateActorFromLayers(OldActor); } World->EditorDestroyActor(OldActor, /*bShouldModifyLevel =*/true); OldToNewInstanceMap.Add(OldActor, NewActor); } else { FName OldName(OldObject->GetFName()); OldObject->Rename(NULL, OldObject->GetOuter(), REN_DoNotDirty | REN_DontCreateRedirectors); NewUObject = NewObject<UObject>(OldObject->GetOuter(), NewClass, OldName); check(NewUObject != nullptr); UEditorEngine::CopyPropertiesForUnrelatedObjects(OldObject, NewUObject); if (UAnimInstance* AnimTree = Cast<UAnimInstance>(NewUObject)) { // Initialising the anim instance isn't enough to correctly set up the skeletal mesh again in a // paused world, need to initialise the skeletal mesh component that contains the anim instance. if (USkeletalMeshComponent* SkelComponent = Cast<USkeletalMeshComponent>(AnimTree->GetOuter())) { SkelComponent->InitAnim(true); } } OldObject->RemoveFromRoot(); OldObject->MarkPendingKill(); OldToNewInstanceMap.Add(OldObject, NewUObject); if (bIsComponent) { UActorComponent* Component = Cast<UActorComponent>(NewUObject); AActor* OwningActor = Component->GetOwner(); if (OwningActor) { OwningActor->ResetOwnedComponents(); // Check to see if they have an editor that potentially needs to be refreshed if (OwningActor->GetClass()->ClassGeneratedBy) { PotentialEditorsForRefreshing.AddUnique(OwningActor->GetClass()->ClassGeneratedBy); } // we need to keep track of actor instances that need // their construction scripts re-ran (since we've just // replaced a component they own) OwnersToReconstruct.Add(OwningActor); } } } // If this original object came from a blueprint and it was in the selected debug set, change the debugging to the new object. if ((CorrespondingBlueprint) && (OldBlueprintDebugObject) && (NewUObject)) { CorrespondingBlueprint->SetObjectBeingDebugged(NewUObject); } if (bLogConversions) { UE_LOG(LogBlueprint, Log, TEXT("Converted instance '%s' to '%s'"), *OldObject->GetPathName(), *NewUObject->GetPathName()); } } } GEditor->OnObjectsReplaced().Remove(OnObjectsReplacedHandle); // Now replace any pointers to the old archetypes/instances with pointers to the new one TArray<UObject*> SourceObjects; TArray<UObject*> DstObjects; OldToNewInstanceMap.GenerateKeyArray(SourceObjects); OldToNewInstanceMap.GenerateValueArray(DstObjects); // Also look for references in new spawned objects. SourceObjects.Append(DstObjects); FReplaceReferenceHelper::IncludeCDO(OldClass, NewClass, OldToNewInstanceMap, SourceObjects, OriginalCDO); FReplaceReferenceHelper::FindAndReplaceReferences(SourceObjects, ObjectsThatShouldUseOldStuff, ObjectsToReplace, OldToNewInstanceMap, ReinstancedObjectsWeakReferenceMap); { BP_SCOPED_COMPILER_EVENT_STAT(EKismetReinstancerStats_ReplacementConstruction); // the process of setting up new replacement actors is split into two // steps (this here, is the second)... // // the "finalization" here runs the replacement actor's construction- // script and is left until late to account for a scenario where the // construction-script attempts to modify another instance of the // same class... if this were to happen above, in the ObjectsToReplace // loop, then accessing that other instance would cause an assert in // UProperty::ContainerPtrToValuePtrInternal() (which appropriatly // complains that the other instance's type doesn't match because it // hasn't been replaced yet... that's why we wait until after // FArchiveReplaceObjectRef to run construction-scripts). for (FActorReplacementHelper& ReplacementActor : ReplacementActors) { ReplacementActor.Finalize(ObjectRemappingHelper.ReplacedObjects); } } SelectedActors->EndBatchSelectOperation(); if (bSelectionChanged) { GEditor->NoteSelectionChange(); } if (GEditor) { // Refresh any editors for objects that we've updated components for for (auto BlueprintAsset : PotentialEditorsForRefreshing) { FBlueprintEditor* BlueprintEditor = static_cast<FBlueprintEditor*>(FAssetEditorManager::Get().FindEditorForAsset(BlueprintAsset, /*bFocusIfOpen =*/false)); if (BlueprintEditor) { BlueprintEditor->RefreshEditors(); } } } // in the case where we're replacing component instances, we need to make // sure to re-run their owner's construction scripts for (AActor* ActorInstance : OwnersToReconstruct) { ActorInstance->RerunConstructionScripts(); } }
void SetLevelVisibility(ULevel* Level, bool bShouldBeVisible, bool bForceLayersVisible) { // Nothing to do if ( Level == NULL ) { return; } // Handle the case of the p-level // The p-level can't be unloaded, so its actors/BSP should just be temporarily hidden/unhidden // Also, intentionally do not force layers visible for the p-level if ( Level->IsPersistentLevel() ) { //create a transaction so we can undo the visibilty toggle const FScopedTransaction Transaction( LOCTEXT( "ToggleLevelVisibility", "Toggle Level Visibility" ) ); if ( Level->bIsVisible != bShouldBeVisible ) { Level->Modify(); } // Set the visibility of each actor in the p-level for ( TArray<AActor*>::TIterator PLevelActorIter( Level->Actors ); PLevelActorIter; ++PLevelActorIter ) { AActor* CurActor = *PLevelActorIter; if ( CurActor && !FActorEditorUtils::IsABuilderBrush(CurActor) && CurActor->bHiddenEdLevel == bShouldBeVisible ) { CurActor->Modify(); CurActor->bHiddenEdLevel = !bShouldBeVisible; CurActor->RegisterAllComponents(); CurActor->MarkComponentsRenderStateDirty(); } } // Set the visibility of each BSP surface in the p-level UModel* CurLevelModel = Level->Model; if ( CurLevelModel ) { CurLevelModel->Modify(); for ( TArray<FBspSurf>::TIterator SurfaceIterator( CurLevelModel->Surfs ); SurfaceIterator; ++SurfaceIterator ) { FBspSurf& CurSurf = *SurfaceIterator; CurSurf.bHiddenEdLevel = !bShouldBeVisible; } } // Add/remove model components from the scene for(int32 ComponentIndex = 0; ComponentIndex < Level->ModelComponents.Num(); ComponentIndex++) { UModelComponent* CurLevelModelCmp = Level->ModelComponents[ComponentIndex]; if(CurLevelModelCmp) { if (bShouldBeVisible && CurLevelModelCmp) { CurLevelModelCmp->RegisterComponentWithWorld(Level->OwningWorld); } else if (!bShouldBeVisible && CurLevelModelCmp->IsRegistered()) { CurLevelModelCmp->UnregisterComponent(); } } } FEditorSupportDelegates::RedrawAllViewports.Broadcast(); } else { ULevelStreaming* StreamingLevel = NULL; if (Level->OwningWorld == NULL || Level->OwningWorld->PersistentLevel != Level ) { StreamingLevel = FLevelUtils::FindStreamingLevel( Level ); } // If were hiding a level, lets make sure to close the level transform mode if its the same level currently selected for edit FEdModeLevel* LevelMode = static_cast<FEdModeLevel*>(GEditorModeTools().GetActiveMode( FBuiltinEditorModes::EM_Level )); if( LevelMode && LevelMode->IsEditing( StreamingLevel ) ) { GEditorModeTools().DeactivateMode( FBuiltinEditorModes::EM_Level ); } //create a transaction so we can undo the visibilty toggle const FScopedTransaction Transaction( LOCTEXT( "ToggleLevelVisibility", "Toggle Level Visibility" ) ); // Handle the case of a streaming level if ( StreamingLevel ) { // We need to set the RF_Transactional to make a streaming level serialize itself. so store the original ones, set the flag, and put the original flags back when done EObjectFlags cachedFlags = StreamingLevel->GetFlags(); StreamingLevel->SetFlags( RF_Transactional ); StreamingLevel->Modify(); StreamingLevel->SetFlags( cachedFlags ); // Set the visibility state for this streaming level. StreamingLevel->bShouldBeVisibleInEditor = bShouldBeVisible; } if( !bShouldBeVisible ) { GEditor->Layers->RemoveLevelLayerInformation( Level ); } // UpdateLevelStreaming sets Level->bIsVisible directly, so we need to make sure it gets saved to the transaction buffer. if ( Level->bIsVisible != bShouldBeVisible ) { Level->Modify(); } if ( StreamingLevel ) { Level->OwningWorld->FlushLevelStreaming(); // In the Editor we expect this operation will complete in a single call check(Level->bIsVisible == bShouldBeVisible); } else if (Level->OwningWorld != NULL) { // In case we level has no associated StreamingLevel, remove or add to world directly if (bShouldBeVisible) { if (!Level->bIsVisible) { Level->OwningWorld->AddToWorld(Level); } } else { Level->OwningWorld->RemoveFromWorld(Level); } // In the Editor we expect this operation will complete in a single call check(Level->bIsVisible == bShouldBeVisible); } if( bShouldBeVisible ) { GEditor->Layers->AddLevelLayerInformation( Level ); } // Force the level's layers to be visible, if desired FEditorSupportDelegates::RedrawAllViewports.Broadcast(); // Iterate over the level's actors, making a list of their layers and unhiding the layers. TTransArray<AActor*>& Actors = Level->Actors; for ( int32 ActorIndex = 0 ; ActorIndex < Actors.Num() ; ++ActorIndex ) { AActor* Actor = Actors[ ActorIndex ]; if ( Actor ) { bool bModified = false; if ( bShouldBeVisible && bForceLayersVisible && GEditor->Layers->IsActorValidForLayer( Actor ) ) { // Make the actor layer visible, if it's not already. if ( Actor->bHiddenEdLayer ) { bModified = Actor->Modify(); Actor->bHiddenEdLayer = false; } const bool bIsVisible = true; GEditor->Layers->SetLayersVisibility( Actor->Layers, bIsVisible ); } // Set the visibility of each actor in the streaming level if ( !FActorEditorUtils::IsABuilderBrush(Actor) && Actor->bHiddenEdLevel == bShouldBeVisible ) { if ( !bModified ) { bModified = Actor->Modify(); } Actor->bHiddenEdLevel = !bShouldBeVisible; if (bShouldBeVisible) { Actor->ReregisterAllComponents(); } else { Actor->UnregisterAllComponents(); } } } } } FEditorDelegates::RefreshLayerBrowser.Broadcast(); // Notify the Scene Outliner, as new Actors may be present in the world. GEngine->BroadcastLevelActorsChanged(); // If the level is being hidden, deselect actors and surfaces that belong to this level. if ( !bShouldBeVisible ) { USelection* SelectedActors = GEditor->GetSelectedActors(); SelectedActors->Modify(); TTransArray<AActor*>& Actors = Level->Actors; for ( int32 ActorIndex = 0 ; ActorIndex < Actors.Num() ; ++ActorIndex ) { AActor* Actor = Actors[ ActorIndex ]; if ( Actor ) { SelectedActors->Deselect( Actor ); } } DeselectAllSurfacesInLevel(Level); // Tell the editor selection status was changed. GEditor->NoteSelectionChange(); } Level->bIsVisible = bShouldBeVisible; }