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() );
}
Beispiel #3
0
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);
		}
	}
}
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 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 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;
}