2014-03-14 14:13:41 -04:00
// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
# include "LevelsPrivatePCH.h"
2014-05-29 17:11:10 -04:00
# include "Engine/LevelScriptBlueprint.h"
2014-04-23 18:35:08 -04:00
# include "LevelViewModel.h"
2014-03-14 14:13:41 -04:00
# include "LevelUtils.h"
# include "EditorLevelUtils.h"
# include "Toolkits/AssetEditorManager.h"
2014-05-21 10:00:58 -04:00
# include "EditorSupportDelegates.h"
2014-08-27 20:35:19 -04:00
# include "SColorPicker.h"
2014-03-14 14:13:41 -04:00
# define LOCTEXT_NAMESPACE "Level"
FLevelViewModel : : FLevelViewModel ( const TWeakObjectPtr < class ULevel > & InLevel ,
const TWeakObjectPtr < class ULevelStreaming > & InLevelStreaming ,
const TWeakObjectPtr < UEditorEngine > & InEditor )
2014-07-30 14:51:27 -04:00
: Editor ( InEditor )
, Level ( InLevel )
2014-03-14 14:13:41 -04:00
, LevelStreaming ( InLevelStreaming )
, LevelActorsCount ( 0 )
{
}
void FLevelViewModel : : Initialize ( )
{
Editor - > RegisterForUndo ( this ) ;
}
FLevelViewModel : : ~ FLevelViewModel ( )
{
Editor - > UnregisterForUndo ( this ) ;
}
void FLevelViewModel : : RefreshStreamingLevelIndex ( )
{
if ( IsLevel ( ) )
{
UWorld * OwningWorld = Level - > OwningWorld ;
check ( OwningWorld ) ;
for ( int32 LevelIndex = 0 ; LevelIndex < OwningWorld - > StreamingLevels . Num ( ) ; + + LevelIndex )
{
ULevelStreaming * StreamingLevel = OwningWorld - > StreamingLevels [ LevelIndex ] ;
if ( Level . Get ( ) = = StreamingLevel - > GetLoadedLevel ( ) )
{
StreamingLevelIndex = LevelIndex ;
LevelStreaming = StreamingLevel ;
break ;
}
}
}
}
FName FLevelViewModel : : GetFName ( ) const
{
if ( IsLevel ( ) )
{
return Level - > GetOutermost ( ) - > GetFName ( ) ;
}
return NAME_None ;
}
FString FLevelViewModel : : GetName ( bool bForceDisplayPath /*=false*/ , bool bDisplayTags /*=true*/ ) const
{
FString DisplayName ;
if ( IsLevel ( ) )
{
if ( bDisplayTags & & IsPersistent ( ) )
{
DisplayName + = LOCTEXT ( " PersistentTag " , " Persistent Level " ) . ToString ( ) ;
}
else
{
DisplayName + = Level - > GetOutermost ( ) - > GetName ( ) ;
2014-05-21 11:16:12 -04:00
bool bDisplayPathsInLevelBrowser = ( GetDefault < ULevelBrowserSettings > ( ) - > bDisplayPaths ) ;
2014-03-14 14:13:41 -04:00
if ( ! ( bDisplayPathsInLevelBrowser | | bForceDisplayPath ) )
{
DisplayName = FPaths : : GetCleanFilename ( DisplayName ) ;
}
}
if ( bDisplayTags & & IsDirty ( ) )
{
DisplayName + = TEXT ( " * " ) ;
}
if ( bDisplayTags & & ( IsCurrent ( ) ) )
{
DisplayName + = LOCTEXT ( " CurrentLevelTag " , " [Current Level] " ) . ToString ( ) ;
}
}
else if ( IsLevelStreaming ( ) )
{
2014-08-25 11:05:29 -04:00
DisplayName + = LevelStreaming - > GetWorldAssetPackageName ( ) ;
2014-03-14 14:13:41 -04:00
2014-05-21 11:16:12 -04:00
bool bDisplayPathsInLevelBrowser = ( GetDefault < ULevelBrowserSettings > ( ) - > bDisplayPaths ) ;
2014-03-14 14:13:41 -04:00
if ( ! ( bDisplayPathsInLevelBrowser | | bForceDisplayPath ) )
{
DisplayName = FPaths : : GetCleanFilename ( DisplayName ) ;
}
if ( bDisplayTags & & IsDirty ( ) )
{
DisplayName + = TEXT ( " * " ) ;
}
DisplayName + = LOCTEXT ( " MissingLevelErrorText " , " [Missing Level] " ) . ToString ( ) ;
}
return DisplayName ;
}
FString FLevelViewModel : : GetDisplayName ( ) const
{
return GetName ( ) ;
}
FString FLevelViewModel : : GetActorCountString ( ) const
{
return FString : : Printf ( TEXT ( " %i " ) , LevelActorsCount ) ;
}
FString FLevelViewModel : : GetLightmassSizeString ( ) const
{
FString MemorySizeString ;
ULevel * CurLevel = Level . Get ( ) ;
2014-05-21 11:16:12 -04:00
if ( CurLevel & & GetDefault < ULevelBrowserSettings > ( ) - > bDisplayLightmassSize )
2014-03-14 14:13:41 -04:00
{
// Update metrics
static const float ByteConversion = 1.0f / 1024.0f ;
float LightmapSize = CurLevel - > LightmapTotalSize * ByteConversion ;
MemorySizeString + = FString : : Printf ( TEXT ( " %.2f " ) , LightmapSize ) ;
}
return MemorySizeString ;
}
FString FLevelViewModel : : GetFileSizeString ( ) const
{
FString MemorySizeString ;
ULevel * CurLevel = Level . Get ( ) ;
2014-05-21 11:16:12 -04:00
if ( CurLevel & & GetDefault < ULevelBrowserSettings > ( ) - > bDisplayFileSize )
2014-03-14 14:13:41 -04:00
{
// Update metrics
static const float ByteConversion = 1.0f / 1024.0f ;
float FileSize = CurLevel - > GetOutermost ( ) - > GetFileSize ( ) * ByteConversion * ByteConversion ;
MemorySizeString + = FString : : Printf ( TEXT ( " %.2f " ) , FileSize ) ;
}
return MemorySizeString ;
}
void FLevelViewModel : : ClearDirtyFlag ( )
{
if ( IsLevel ( ) )
{
return Level - > GetOutermost ( ) - > SetDirtyFlag ( false ) ;
}
else if ( IsLevelStreaming ( ) )
{
return LevelStreaming - > GetOutermost ( ) - > SetDirtyFlag ( false ) ;
}
}
bool FLevelViewModel : : IsDirty ( ) const
{
if ( IsLevel ( ) )
{
return Level - > GetOutermost ( ) - > IsDirty ( ) ;
}
else if ( IsLevelStreaming ( ) )
{
return LevelStreaming - > GetOutermost ( ) - > IsDirty ( ) ;
}
else
{
return false ;
}
}
bool FLevelViewModel : : IsCurrent ( ) const
{
if ( IsLevel ( ) )
{
return Level - > IsCurrentLevel ( ) ;
}
else
{
return false ;
}
}
bool FLevelViewModel : : IsPersistent ( ) const
{
if ( ! Level . IsValid ( ) )
{
return false ;
}
return ( Level - > IsPersistentLevel ( ) ) ;
}
bool FLevelViewModel : : IsLevel ( ) const
{
return Level . IsValid ( ) ;
}
bool FLevelViewModel : : IsLevelStreaming ( ) const
{
return LevelStreaming . IsValid ( ) ;
}
bool FLevelViewModel : : IsVisible ( ) const
{
if ( ! Level . IsValid ( ) )
{
return false ;
}
return ( FLevelUtils : : IsLevelVisible ( Level . Get ( ) ) ) ;
}
void FLevelViewModel : : ToggleVisibility ( )
{
if ( ! Level . IsValid ( ) )
{
return ;
}
SetVisible ( ! IsVisible ( ) ) ;
}
void FLevelViewModel : : SetVisible ( bool bVisible )
{
//don't create unnecessary transactions
if ( IsVisible ( ) = = bVisible )
{
return ;
}
const bool oldIsDirty = IsDirty ( ) ;
const FScopedTransaction Transaction ( LOCTEXT ( " ToggleVisibility " , " Toggle Level Visibility " ) ) ;
//this call hides all owned actors, etc
2014-07-15 04:48:45 -04:00
EditorLevelUtils : : SetLevelVisibility ( Level . Get ( ) , bVisible , false ) ;
2014-03-14 14:13:41 -04:00
if ( ! oldIsDirty )
{
// don't set the dirty flag if we're just changing the visibility of the level within the editor
ClearDirtyFlag ( ) ;
}
}
bool FLevelViewModel : : IsReadOnly ( ) const
{
const UPackage * pPackage = Cast < UPackage > ( Level - > GetOutermost ( ) ) ;
if ( pPackage )
{
FString PackageFileName ;
if ( FPackageName : : DoesPackageExist ( pPackage - > GetName ( ) , NULL , & PackageFileName ) )
{
return IFileManager : : Get ( ) . IsReadOnly ( * PackageFileName ) ;
}
}
return false ;
}
bool FLevelViewModel : : IsLocked ( ) const
{
if ( ! Level . IsValid ( ) )
{
return false ;
}
// Don't permit spawning in read only levels if they are locked
if ( GIsEditor & & ! GIsEditorLoadingPackage )
{
if ( GEngine & & GEngine - > bLockReadOnlyLevels )
{
if ( IsReadOnly ( ) )
{
return true ;
}
}
}
return ( FLevelUtils : : IsLevelLocked ( Level . Get ( ) ) ) ;
}
bool FLevelViewModel : : IsValid ( ) const
{
bool bValid = Level . IsValid ( ) | | LevelStreaming . IsValid ( ) ;
return bValid ;
}
void FLevelViewModel : : ToggleLock ( )
{
if ( ! Level . IsValid ( ) )
{
return ;
}
SetLocked ( ! IsLocked ( ) ) ;
}
/**
* 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 FLevelViewModel : : SetStreamingClass ( UClass * LevelStreamingClass )
{
if ( IsPersistent ( ) | | ! IsLevel ( ) )
{
// Invalid operations for the persistent level
return ;
}
ULevelStreaming * StreamingLevel = FLevelUtils : : FindStreamingLevel ( Level . Get ( ) ) ;
if ( StreamingLevel )
{
EditorLevelUtils : : SetStreamingClassForLevel ( StreamingLevel , LevelStreamingClass ) ;
}
}
void FLevelViewModel : : MakeLevelCurrent ( )
{
// If something is selected and not already current . . .
if ( Level . IsValid ( ) & & ! Level . Get ( ) - > IsCurrentLevel ( ) )
{
EditorLevelUtils : : MakeLevelCurrent ( Level . Get ( ) ) ;
}
Refresh ( ) ;
}
void FLevelViewModel : : Save ( )
{
if ( ! IsLevel ( ) )
{
return ;
}
if ( ! IsVisible ( ) )
{
FMessageDialog : : Open ( EAppMsgType : : Ok , NSLOCTEXT ( " UnrealEd " , " UnableToSaveInvisibleLevels " , " Save aborted. Levels must be made visible before they can be saved. " ) ) ;
return ;
}
else if ( IsLocked ( ) )
{
FMessageDialog : : Open ( EAppMsgType : : Ok , NSLOCTEXT ( " UnrealEd " , " UnableToSaveLockedLevels " , " Save aborted. Level must be unlocked before it can be saved. " ) ) ;
return ;
}
// Prompt the user to check out the level from source control before saving if it's currently under source control
if ( FEditorFileUtils : : PromptToCheckoutLevels ( false , Level . Get ( ) ) )
{
FEditorFileUtils : : SaveLevel ( Level . Get ( ) ) ;
}
}
bool FLevelViewModel : : HasKismet ( ) const
{
if ( ! Level . IsValid ( ) )
{
return false ;
}
return true ;
}
void FLevelViewModel : : OpenKismet ( )
{
if ( ! Level . IsValid ( ) )
{
return ;
}
ULevelScriptBlueprint * LevelScriptBlueprint = Level . Get ( ) - > GetLevelScriptBlueprint ( ) ;
if ( LevelScriptBlueprint )
{
FAssetEditorManager : : Get ( ) . OpenEditorForAsset ( LevelScriptBlueprint ) ;
}
else
{
FMessageDialog : : Open ( EAppMsgType : : Ok , NSLOCTEXT ( " UnrealEd " , " UnableToCreateLevelScript " , " Unable to find or create a level blueprint for this level. " ) ) ;
}
}
FSlateColor FLevelViewModel : : GetColor ( ) const
{
if ( Level . IsValid ( ) & & ! Level - > IsPersistentLevel ( ) )
{
ULevelStreaming * StreamingLevel = FLevelUtils : : FindStreamingLevel ( Level . Get ( ) ) ;
if ( StreamingLevel )
{
2014-07-28 17:16:21 -04:00
return StreamingLevel - > LevelColor ;
2014-03-14 14:13:41 -04:00
}
}
2014-07-28 17:16:21 -04:00
return FLinearColor : : White ;
2014-03-14 14:13:41 -04:00
}
void FLevelViewModel : : OnColorPickerCancelled ( FLinearColor Color )
{
bColorPickerOK = false ;
}
void FLevelViewModel : : ChangeColor ( const TSharedRef < SWidget > & InPickerParentWidget )
{
if ( ! Level . IsValid ( ) )
{
return ;
}
if ( ! Level - > IsPersistentLevel ( ) )
{
// Initialize the color data for the picker window.
ULevelStreaming * StreamingLevel = FLevelUtils : : FindStreamingLevel ( Level . Get ( ) ) ;
check ( StreamingLevel ) ;
2014-07-28 17:16:21 -04:00
FLinearColor NewColor = StreamingLevel - > LevelColor ;
TArray < FLinearColor * > ColorArray ;
2014-03-14 14:13:41 -04:00
ColorArray . Add ( & NewColor ) ;
FColorPickerArgs PickerArgs ;
PickerArgs . bIsModal = true ;
PickerArgs . DisplayGamma = TAttribute < float > : : Create ( TAttribute < float > : : FGetter : : CreateUObject ( GEngine , & UEngine : : GetDisplayGamma ) ) ;
2014-07-28 17:16:21 -04:00
PickerArgs . LinearColorArray = & ColorArray ;
2014-03-14 14:13:41 -04:00
PickerArgs . OnColorPickerCancelled = FOnColorPickerCancelled : : CreateSP ( this , & FLevelViewModel : : OnColorPickerCancelled ) ;
PickerArgs . ParentWidget = InPickerParentWidget ;
// ensure this is true, will be set to false in OnColorPickerCancelled if necessary
bColorPickerOK = true ;
if ( OpenColorPicker ( PickerArgs ) )
{
if ( bColorPickerOK )
{
2014-07-28 17:16:21 -04:00
StreamingLevel - > LevelColor = NewColor ;
2014-03-14 14:13:41 -04:00
StreamingLevel - > Modify ( ) ;
// Update the loaded level's components so the change in color will apply immediately
ULevel * LoadedLevel = StreamingLevel - > GetLoadedLevel ( ) ;
if ( LoadedLevel )
{
LoadedLevel - > UpdateLevelComponents ( false ) ;
}
ULevel : : LevelDirtiedEvent . Broadcast ( ) ;
}
FEditorSupportDelegates : : RedrawAllViewports . Broadcast ( ) ;
}
}
}
//@todo: add actor drag+drop support
2014-04-23 18:06:41 -04:00
bool FLevelViewModel : : CanAssignActors ( const TArray < TWeakObjectPtr < AActor > > Actors , FText & OutMessage ) const
2014-03-14 14:13:41 -04:00
{
return false ;
}
2014-04-23 18:06:41 -04:00
bool FLevelViewModel : : CanAssignActor ( const TWeakObjectPtr < AActor > Actor , FText & OutMessage ) const
2014-03-14 14:13:41 -04:00
{
return true ;
}
void FLevelViewModel : : AppendActors ( TArray < TWeakObjectPtr < AActor > > & InActors ) const
{
}
void FLevelViewModel : : AppendActorsOfSpecificType ( TArray < TWeakObjectPtr < AActor > > & InActors , const TWeakObjectPtr < UClass > & Class )
{
}
void FLevelViewModel : : AddActor ( const TWeakObjectPtr < AActor > & Actor )
{
}
void FLevelViewModel : : AddActors ( const TArray < TWeakObjectPtr < AActor > > & Actors )
{
}
void FLevelViewModel : : RemoveActors ( const TArray < TWeakObjectPtr < AActor > > & Actors )
{
}
void FLevelViewModel : : RemoveActor ( const TWeakObjectPtr < AActor > & Actor )
{
}
void FLevelViewModel : : SelectActors ( bool bSelect , bool bNotify , bool bSelectEvenIfHidden , const TSharedPtr < IFilter < const TWeakObjectPtr < AActor > & > > & Filter )
{
if ( ! Level . IsValid ( ) | | IsLocked ( ) )
{
return ;
}
Editor - > GetSelectedActors ( ) - > BeginBatchSelectOperation ( ) ;
bool bChangesOccurred = false ;
// Iterate over all actors, looking for actors in this level.
ULevel * RawLevel = Level . Get ( ) ;
for ( int32 ActorIndex = 2 ; ActorIndex < RawLevel - > Actors . Num ( ) ; + + ActorIndex )
{
AActor * Actor = RawLevel - > Actors [ ActorIndex ] ;
if ( Actor )
{
if ( Filter . IsValid ( ) & & ! Filter - > PassesFilter ( Actor ) )
{
continue ;
}
bool bNotifyForActor = false ;
Editor - > GetSelectedActors ( ) - > Modify ( ) ;
Editor - > SelectActor ( Actor , bSelect , bNotifyForActor , bSelectEvenIfHidden ) ;
bChangesOccurred = true ;
}
}
Editor - > GetSelectedActors ( ) - > EndBatchSelectOperation ( ) ;
if ( bNotify )
{
Editor - > NoteSelectionChange ( ) ;
}
}
void FLevelViewModel : : SelectActorsOfSpecificType ( const TWeakObjectPtr < UClass > & Class )
{
}
void FLevelViewModel : : SetDataSource ( const TWeakObjectPtr < ULevel > & InLevel )
{
if ( Level = = InLevel )
{
return ;
}
Level = InLevel ;
Refresh ( ) ;
}
const TWeakObjectPtr < ULevel > FLevelViewModel : : GetLevel ( )
{
return Level ;
}
const TWeakObjectPtr < ULevelStreaming > FLevelViewModel : : GetLevelStreaming ( )
{
return LevelStreaming ;
}
void FLevelViewModel : : OnLevelsChanged ( const ELevelsAction : : Type Action , const ULevel * ChangedLevel , const FName & ChangedProperty )
{
ChangedEvent . Broadcast ( ) ;
}
void FLevelViewModel : : Refresh ( )
{
OnLevelsChanged ( ELevelsAction : : Reset , NULL , NAME_None ) ;
}
void FLevelViewModel : : UpdateLevelActorsCount ( )
{
LevelActorsCount = 0 ;
ULevel * CurLevel = Level . Get ( ) ;
if ( CurLevel )
{
// Count the actors contained in these levels
// NOTE: We subtract two here to omit "default actors" in the count (default brush, and WorldSettings)
LevelActorsCount = CurLevel - > Actors . Num ( ) - 2 ;
// Count deleted actors
int32 NumDeletedActors = 0 ;
for ( int32 ActorIdx = 0 ; ActorIdx < CurLevel - > Actors . Num ( ) ; + + ActorIdx )
{
if ( ! CurLevel - > Actors [ ActorIdx ] )
{
+ + NumDeletedActors ;
}
}
// Subtract deleted actors from the actor count
LevelActorsCount - = NumDeletedActors ;
}
}
# undef LOCTEXT_NAMESPACE