Files
UnrealEngineUWP/Engine/Source/Editor/Levels/Private/LevelViewModel.cpp
Bob Tellez 2a61ba9f76 [AUTOMERGE]
#UE4 Deprecated ULevelStreaming::PackageName in favor of the new WorldAsset TAssetPtr. This will allow editor tools to properly follow references from persistent levels to sublevels. All existing usage of PackageName has been replaced with GetWorldAssetPackageName() and SetWorldAssetByPackageName().

--------
Integrated using branch Ue4-To-UE4-Fortnite-Simple (reversed) of change#2269772 by Bob.Tellez on 2014/08/24 16:49:38.

[CL 2269774 by Bob Tellez in Main branch]
2014-08-25 11:05:29 -04:00

651 lines
14 KiB
C++

// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
#include "LevelsPrivatePCH.h"
#include "Engine/LevelScriptBlueprint.h"
#include "LevelViewModel.h"
#include "LevelUtils.h"
#include "EditorLevelUtils.h"
#include "Toolkits/AssetEditorManager.h"
#include "EditorSupportDelegates.h"
#define LOCTEXT_NAMESPACE "Level"
FLevelViewModel::FLevelViewModel( const TWeakObjectPtr< class ULevel >& InLevel,
const TWeakObjectPtr< class ULevelStreaming >& InLevelStreaming,
const TWeakObjectPtr< UEditorEngine >& InEditor )
: Editor( InEditor )
, Level( InLevel )
, 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();
bool bDisplayPathsInLevelBrowser = (GetDefault<ULevelBrowserSettings>()->bDisplayPaths);
if ( !(bDisplayPathsInLevelBrowser || bForceDisplayPath) )
{
DisplayName = FPaths::GetCleanFilename(DisplayName);
}
}
if ( bDisplayTags && IsDirty() )
{
DisplayName += TEXT(" * ");
}
if ( bDisplayTags && (IsCurrent()) )
{
DisplayName += LOCTEXT("CurrentLevelTag", " [Current Level]").ToString();
}
}
else if ( IsLevelStreaming() )
{
DisplayName += LevelStreaming->GetWorldAssetPackageName();
bool bDisplayPathsInLevelBrowser = (GetDefault<ULevelBrowserSettings>()->bDisplayPaths);
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();
if ( CurLevel && GetDefault<ULevelBrowserSettings>()->bDisplayLightmassSize )
{
// 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();
if ( CurLevel && GetDefault<ULevelBrowserSettings>()->bDisplayFileSize )
{
// 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
EditorLevelUtils::SetLevelVisibility( Level.Get(), bVisible, false );
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 )
{
return StreamingLevel->LevelColor;
}
}
return FLinearColor::White;
}
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 );
FLinearColor NewColor = StreamingLevel->LevelColor;
TArray<FLinearColor*> ColorArray;
ColorArray.Add(&NewColor);
FColorPickerArgs PickerArgs;
PickerArgs.bIsModal = true;
PickerArgs.DisplayGamma = TAttribute<float>::Create( TAttribute<float>::FGetter::CreateUObject(GEngine, &UEngine::GetDisplayGamma) );
PickerArgs.LinearColorArray = &ColorArray;
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 )
{
StreamingLevel->LevelColor = NewColor;
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
bool FLevelViewModel::CanAssignActors( const TArray< TWeakObjectPtr<AActor> > Actors, FText& OutMessage ) const
{
return false;
}
bool FLevelViewModel::CanAssignActor(const TWeakObjectPtr<AActor> Actor, FText& OutMessage) const
{
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