Ejemplo n.º 1
0
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);
	}
}
Ejemplo n.º 3
0
void UUnrealEdEngine::SetCurrentClass( UClass* InClass )
{
	USelection* SelectionSet = GetSelectedObjects();
	SelectionSet->DeselectAll( UClass::StaticClass() );

	if(InClass != NULL)
	{
		SelectionSet->Select( InClass );
	}
}
Ejemplo n.º 4
0
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;
	}
}
Ejemplo n.º 5
0
/**
* 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() );
}
Ejemplo n.º 6
0
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);
			}
		}
	}
}
Ejemplo n.º 7
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);
		}
	}
}
Ejemplo n.º 8
0
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();
}
Ejemplo n.º 11
0
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();
	}
}
Ejemplo n.º 12
0
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();
}
Ejemplo n.º 16
0
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();
	}
}
Ejemplo n.º 17
-1
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;
}