void UUnrealEdEngine::DrawComponentVisualizersHUD(const FViewport* Viewport, const FSceneView* View, FCanvas* Canvas) { // Iterate over all selected actors for (FSelectionIterator It(GetSelectedActorIterator()); It; ++It) { AActor* Actor = Cast<AActor>(*It); if (Actor != NULL) { // Then iterate over components of that actor TInlineComponentArray<UActorComponent*> Components; Actor->GetComponents(Components); for (int32 CompIdx = 0; CompIdx<Components.Num(); CompIdx++) { UActorComponent* Comp = Components[CompIdx]; if (Comp->IsRegistered()) { // Try and find a visualizer TSharedPtr<FComponentVisualizer> Visualizer = FindComponentVisualizer(Comp->GetClass()); if (Visualizer.IsValid()) { Visualizer->DrawVisualizationHUD(Comp, Viewport, View, Canvas); } } } } } }
void UUnrealEdEngine::MakeSelectedActorsLevelCurrent() { ULevel* LevelToMakeCurrent = NULL; // Look to the selected actors for the level to make current. // If actors from multiple levels are selected, do nothing. for ( FSelectionIterator It( GetSelectedActorIterator() ) ; It ; ++It ) { AActor* Actor = static_cast<AActor*>( *It ); checkSlow( Actor->IsA(AActor::StaticClass()) ); ULevel* ActorLevel = Actor->GetLevel(); if ( !LevelToMakeCurrent ) { // First assignment. LevelToMakeCurrent = ActorLevel; } else if ( LevelToMakeCurrent != ActorLevel ) { // Actors from multiple levels are selected -- abort. LevelToMakeCurrent = NULL; break; } } // Change the current level to something different if ( LevelToMakeCurrent && !LevelToMakeCurrent->IsCurrentLevel() ) { EditorLevelUtils::MakeLevelCurrent( LevelToMakeCurrent ); } }
void UUnrealEdEngine::UpdateFloatingPropertyWindows() { TArray<UObject*> SelectedObjects; bool bProcessed = false; if (GetSelectedActorCount() == 1) { FSelectionIterator It( GetSelectedActorIterator() ); if ( It ) { AActor* Actor = static_cast<AActor*>( *It ); checkSlow( Actor->IsA(AActor::StaticClass()) ); if ( !Actor->IsPendingKill() ) { // Currently only for Landscape // Landscape uses Component Selection bProcessed = Actor->GetSelectedComponents(SelectedObjects); } } } if (!bProcessed) { // Assemble a set of valid selected actors. for ( FSelectionIterator It( GetSelectedActorIterator() ) ; It ; ++It ) { AActor* Actor = static_cast<AActor*>( *It ); checkSlow( Actor->IsA(AActor::StaticClass()) ); if ( !Actor->IsPendingKill() ) { SelectedObjects.Add( Actor ); } } } UpdateFloatingPropertyWindowsFromActorList( SelectedObjects ); }
void UUnrealEdEngine::UpdateFloatingPropertyWindows(bool bForceRefresh) { TArray<UObject*> SelectedObjects; // Assemble a set of valid selected actors. for (FSelectionIterator It = GetSelectedActorIterator(); It; ++It) { AActor* Actor = static_cast<AActor*>(*It); checkSlow(Actor->IsA(AActor::StaticClass())); if (!Actor->IsPendingKill()) { SelectedObjects.Add(Actor); } } UpdateFloatingPropertyWindowsFromActorList(SelectedObjects, bForceRefresh); }
void UUnrealEdEngine::FinishAllSnaps() { if(!IsRunningCommandlet()) { if( ClickFlags & CF_MOVE_ACTOR ) { ClickFlags &= ~CF_MOVE_ACTOR; for ( FSelectionIterator It( GetSelectedActorIterator() ) ; It ; ++It ) { AActor* Actor = static_cast<AActor*>( *It ); checkSlow( Actor->IsA(AActor::StaticClass()) ); Actor->Modify(); Actor->InvalidateLightingCache(); Actor->PostEditMove( true ); } } } }
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 UUnrealEdEngine::UpdatePivotLocationForSelection( bool bOnChange ) { // Pick a new common pivot, or not. AActor* SingleActor = nullptr; USceneComponent* SingleComponent = nullptr; if (GetSelectedComponentCount() > 0) { for (FSelectedEditableComponentIterator It(*GetSelectedComponents()); It; ++It) { UActorComponent* Component = CastChecked<UActorComponent>(*It); AActor* ComponentOwner = Component->GetOwner(); if (ComponentOwner != nullptr) { auto SelectedActors = GetSelectedActors(); const bool bIsOwnerSelected = SelectedActors->IsSelected(ComponentOwner); check(bIsOwnerSelected); if (ComponentOwner->GetWorld() == GWorld) { SingleActor = ComponentOwner; if (Component->IsA<USceneComponent>()) { SingleComponent = CastChecked<USceneComponent>(Component); } const bool IsTemplate = ComponentOwner->IsTemplate(); const bool LevelLocked = !FLevelUtils::IsLevelLocked(ComponentOwner->GetLevel()); check(IsTemplate || LevelLocked); } } } } else { for (FSelectionIterator It(GetSelectedActorIterator()); It; ++It) { AActor* Actor = static_cast<AActor*>(*It); checkSlow(Actor->IsA(AActor::StaticClass())); if (Actor->GetWorld() == GWorld) { const bool IsTemplate = Actor->IsTemplate(); const bool LevelLocked = !FLevelUtils::IsLevelLocked(Actor->GetLevel()); check(IsTemplate || LevelLocked); SingleActor = Actor; } } } if (SingleComponent != NULL) { SetPivot(SingleComponent->GetComponentLocation(), false, true); } else if( SingleActor != NULL ) { // For geometry mode use current pivot location as it's set to selected face, not actor FEditorModeTools& Tools = GLevelEditorModeTools(); if( Tools.IsModeActive(FBuiltinEditorModes::EM_Geometry) == false || bOnChange == true ) { // Set pivot point to the actor's location FVector PivotPoint = SingleActor->GetActorLocation(); // If grouping is active, see if this actor is part of a locked group and use that pivot instead if(GEditor->bGroupingActive) { AGroupActor* ActorGroupRoot = AGroupActor::GetRootForActor(SingleActor, true, true); if(ActorGroupRoot) { PivotPoint = ActorGroupRoot->GetActorLocation(); } } SetPivot( PivotPoint, false, true ); } } else { ResetPivot(); } }
void UUnrealEdEngine::SetPivot( FVector NewPivot, bool bSnapPivotToGrid, bool bIgnoreAxis, bool bAssignPivot/*=false*/ ) { FEditorModeTools& EditorModeTools = GLevelEditorModeTools(); if( !bIgnoreAxis ) { // Don't stomp on orthonormal axis. if( NewPivot.X==0 ) NewPivot.X=EditorModeTools.PivotLocation.X; if( NewPivot.Y==0 ) NewPivot.Y=EditorModeTools.PivotLocation.Y; if( NewPivot.Z==0 ) NewPivot.Z=EditorModeTools.PivotLocation.Z; } // Set the pivot. //EditorModeTools.CachedLocation = NewPivot; // Don't set the cached location, this is our pre-move point EditorModeTools.PivotLocation = NewPivot; EditorModeTools.SnappedLocation = NewPivot; EditorModeTools.GridBase = FVector::ZeroVector; if( bSnapPivotToGrid ) { FRotator DummyRotator(0,0,0); FSnappingUtils::SnapToBSPVertex( EditorModeTools.SnappedLocation, EditorModeTools.GridBase, DummyRotator ); EditorModeTools.PivotLocation = EditorModeTools.SnappedLocation; } // Check all actors. int32 Count=0, SnapCount=0; //default to using the x axis for the translate rotate widget EditorModeTools.TranslateRotateXAxisAngle = 0.0f; EditorModeTools.TranslateRotate2DAngle = 0.0f; FVector TranslateRotateWidgetWorldXAxis; FVector Widget2DWorldXAxis; AActor* LastSelectedActor = NULL; for ( FSelectionIterator It( GetSelectedActorIterator() ) ; It ; ++It ) { AActor* Actor = static_cast<AActor*>( *It ); checkSlow( Actor->IsA(AActor::StaticClass()) ); if (Count==0) { TranslateRotateWidgetWorldXAxis = Actor->ActorToWorld().TransformVector(FVector(1.0f, 0.0f, 0.0f)); //get the xy plane project of this vector TranslateRotateWidgetWorldXAxis.Z = 0.0f; if (!TranslateRotateWidgetWorldXAxis.Normalize()) { TranslateRotateWidgetWorldXAxis = FVector(1.0f, 0.0f, 0.0f); } Widget2DWorldXAxis = Actor->ActorToWorld().TransformVector(FVector(1, 0, 0)); Widget2DWorldXAxis.Y = 0; if (!Widget2DWorldXAxis.Normalize()) { Widget2DWorldXAxis = FVector(1, 0, 0); } } LastSelectedActor = Actor; ++Count; ++SnapCount; } if( bAssignPivot && LastSelectedActor && GEditor->bGroupingActive ) { // set group pivot for the root-most group AGroupActor* ActorGroupRoot = AGroupActor::GetRootForActor(LastSelectedActor, true, true); if(ActorGroupRoot) { ActorGroupRoot->SetActorLocation( EditorModeTools.PivotLocation, false ); } } //if there are multiple actors selected, just use the x-axis for the "translate/rotate" or 2D widgets if (Count == 1) { EditorModeTools.TranslateRotateXAxisAngle = TranslateRotateWidgetWorldXAxis.Rotation().Yaw; EditorModeTools.TranslateRotate2DAngle = FMath::RadiansToDegrees(FMath::Atan2(Widget2DWorldXAxis.Z, Widget2DWorldXAxis.X)); } // Update showing. EditorModeTools.PivotShown = SnapCount>0 || Count>1; }