2019-12-26 15:33:43 -05:00
// Copyright Epic Games, Inc. All Rights Reserved.
2014-03-14 14:13:41 -04:00
2016-11-23 15:48:37 -05:00
# include "LayerViewModel.h"
# include "Editor/EditorEngine.h"
# include "ScopedTransaction.h"
# include "Misc/DelegateFilter.h"
2014-03-14 14:13:41 -04:00
# define LOCTEXT_NAMESPACE "Layer"
2019-09-10 11:35:20 -04:00
DEFINE_LOG_CATEGORY_STATIC ( LogLayerViewModel , Fatal , All ) ;
FLayerViewModel : : FLayerViewModel ( const TWeakObjectPtr < ULayer > & InLayer , const TWeakObjectPtr < UEditorEngine > & InEditor )
: Editor ( InEditor )
, WorldLayers ( Editor . IsValid ( ) ? Editor - > GetEditorSubsystem < ULayersSubsystem > ( ) : nullptr )
2014-07-31 15:43:08 -04:00
, Layer ( InLayer )
2014-03-14 14:13:41 -04:00
{
2019-09-10 11:35:20 -04:00
// Sanity checks
if ( ! Editor . IsValid ( ) )
{
UE_LOG ( LogLayerViewModel , Fatal , TEXT ( " This function requires Editor.IsValid() == true. " ) ) ;
}
else if ( WorldLayers = = nullptr )
{
UE_LOG ( LogLayerViewModel , Fatal , TEXT ( " This function requires Editor->GetEditorSubsystem<ULayersSubsystem>() to be already loaded rather than being a nullptr. " ) ) ;
}
2014-03-14 14:13:41 -04:00
}
void FLayerViewModel : : Initialize ( )
{
WorldLayers - > OnLayersChanged ( ) . AddSP ( this , & FLayerViewModel : : OnLayersChanged ) ;
if ( Editor . IsValid ( ) )
{
Editor - > RegisterForUndo ( this ) ;
}
RefreshActorStats ( ) ;
}
FLayerViewModel : : ~ FLayerViewModel ( )
{
WorldLayers - > OnLayersChanged ( ) . RemoveAll ( this ) ;
if ( Editor . IsValid ( ) )
{
Editor - > UnregisterForUndo ( this ) ;
}
}
FName FLayerViewModel : : GetFName ( ) const
{
if ( ! Layer . IsValid ( ) )
{
return NAME_None ;
}
2020-08-11 01:36:57 -04:00
return Layer - > GetLayerName ( ) ;
2014-03-14 14:13:41 -04:00
}
FString FLayerViewModel : : GetName ( ) const
{
FString name ;
if ( Layer . IsValid ( ) )
{
2020-08-11 01:36:57 -04:00
name = Layer - > GetLayerName ( ) . ToString ( ) ;
2014-03-14 14:13:41 -04:00
}
return name ;
}
FText FLayerViewModel : : GetNameAsText ( ) const
{
if ( ! Layer . IsValid ( ) )
{
return FText : : GetEmpty ( ) ;
}
2020-08-11 01:36:57 -04:00
return FText : : FromName ( Layer - > GetLayerName ( ) ) ;
2014-03-14 14:13:41 -04:00
}
bool FLayerViewModel : : IsVisible ( ) const
{
if ( ! Layer . IsValid ( ) )
{
return false ;
}
2020-08-11 01:36:57 -04:00
return Layer - > IsVisible ( ) ;
}
2014-03-14 14:13:41 -04:00
void FLayerViewModel : : ToggleVisibility ( )
{
if ( ! Layer . IsValid ( ) )
{
return ;
}
2019-01-10 17:26:53 -05:00
VisibilityToggledEvent . Broadcast ( AsShared ( ) ) ;
2014-03-14 14:13:41 -04:00
}
2014-04-23 16:38:40 -04:00
bool FLayerViewModel : : CanRenameTo ( const FName & NewLayerName , FString & OutMessage ) const
{
if ( NewLayerName . IsNone ( ) )
{
OutMessage = LOCTEXT ( " EmptyLayerName " , " Layer must be given a name " ) . ToString ( ) ;
return false ;
}
2019-09-10 11:35:20 -04:00
ULayer * FoundLayer ;
if ( WorldLayers - > TryGetLayer ( NewLayerName , FoundLayer ) & & FoundLayer ! = Layer . Get ( ) )
2014-04-23 16:38:40 -04:00
{
OutMessage = LOCTEXT ( " RenameFailed_AlreadyExists " , " This layer already exists " ) . ToString ( ) ;
return false ;
}
return true ;
}
void FLayerViewModel : : RenameTo ( const FName & NewLayerName )
2014-03-14 14:13:41 -04:00
{
if ( ! Layer . IsValid ( ) )
{
return ;
}
2020-08-11 01:36:57 -04:00
if ( Layer - > GetLayerName ( ) = = NewLayerName )
2014-03-14 14:13:41 -04:00
{
return ;
}
int32 LayerIndex = 0 ;
2014-04-23 16:38:40 -04:00
FName UniqueNewLayerName = NewLayerName ;
2019-09-10 11:35:20 -04:00
while ( WorldLayers - > IsLayer ( UniqueNewLayerName ) )
2014-03-14 14:13:41 -04:00
{
2014-04-23 16:38:40 -04:00
UniqueNewLayerName = FName ( * FString : : Printf ( TEXT ( " %s_%d " ) , * NewLayerName . ToString ( ) , + + LayerIndex ) ) ;
2014-03-14 14:13:41 -04:00
}
const FScopedTransaction Transaction ( LOCTEXT ( " RenameTo " , " Rename Layer " ) ) ;
2020-08-11 01:36:57 -04:00
WorldLayers - > RenameLayer ( Layer - > GetLayerName ( ) , UniqueNewLayerName ) ;
2014-03-14 14:13:41 -04:00
}
2014-04-23 18:06:41 -04:00
bool FLayerViewModel : : CanAssignActors ( const TArray < TWeakObjectPtr < AActor > > Actors , FText & OutMessage ) const
2014-03-14 14:13:41 -04:00
{
if ( ! Layer . IsValid ( ) )
{
2014-04-23 18:06:41 -04:00
OutMessage = LOCTEXT ( " InvalidLayer " , " Invalid Layer " ) ;
2014-03-14 14:13:41 -04:00
return false ;
}
2014-04-23 18:06:41 -04:00
FFormatNamedArguments LayerArgs ;
2020-08-11 01:36:57 -04:00
LayerArgs . Add ( TEXT ( " LayerName " ) , FText : : FromName ( Layer - > GetLayerName ( ) ) ) ;
2014-04-23 18:06:41 -04:00
2014-03-14 14:13:41 -04:00
bool bHasValidActorToAssign = false ;
int32 bAlreadyAssignedActors = 0 ;
for ( auto ActorIt = Actors . CreateConstIterator ( ) ; ActorIt ; + + ActorIt )
{
TWeakObjectPtr < AActor > Actor = * ActorIt ;
if ( ! Actor . IsValid ( ) )
{
2014-04-23 18:06:41 -04:00
OutMessage = FText : : Format ( LOCTEXT ( " InvalidActors " , " Cannot add invalid Actors to {LayerName} " ) , LayerArgs ) ;
2014-03-14 14:13:41 -04:00
return false ;
}
2014-04-23 18:06:41 -04:00
FFormatNamedArguments ActorArgs ;
ActorArgs . Add ( TEXT ( " ActorName " ) , FText : : FromName ( Actor - > GetFName ( ) ) ) ;
2019-09-10 11:35:20 -04:00
if ( ! WorldLayers - > IsActorValidForLayer ( Actor . Get ( ) ) )
2014-03-14 14:13:41 -04:00
{
2014-04-23 18:06:41 -04:00
OutMessage = FText : : Format ( LOCTEXT ( " InvalidLayers " , " Actor '{ActorName}' cannot be associated with Layers " ) , ActorArgs ) ;
2014-03-14 14:13:41 -04:00
return false ;
}
2020-08-11 01:36:57 -04:00
if ( Actor - > Layers . Contains ( Layer - > GetLayerName ( ) ) )
2014-03-14 14:13:41 -04:00
{
bAlreadyAssignedActors + + ;
}
else
{
bHasValidActorToAssign = true ;
}
}
if ( bAlreadyAssignedActors = = Actors . Num ( ) )
{
2014-04-23 18:06:41 -04:00
OutMessage = FText : : Format ( LOCTEXT ( " AlreadyAssignedActors " , " All Actors already assigned to {LayerName} " ) , LayerArgs ) ;
2014-03-14 14:13:41 -04:00
return false ;
}
if ( bHasValidActorToAssign )
{
2014-04-23 18:06:41 -04:00
OutMessage = FText : : Format ( LOCTEXT ( " AssignActors " , " Assign Actors to {LayerName} " ) , LayerArgs ) ;
2014-03-14 14:13:41 -04:00
return true ;
}
2014-04-23 18:06:41 -04:00
OutMessage = FText : : GetEmpty ( ) ;
2014-03-14 14:13:41 -04:00
return false ;
}
2014-04-23 18:06:41 -04:00
bool FLayerViewModel : : CanAssignActor ( const TWeakObjectPtr < AActor > Actor , FText & OutMessage ) const
2014-03-14 14:13:41 -04:00
{
if ( ! Layer . IsValid ( ) )
{
2014-04-23 18:06:41 -04:00
OutMessage = LOCTEXT ( " InvalidLayer " , " Invalid Layer " ) ;
2014-03-14 14:13:41 -04:00
return false ;
}
2014-04-23 18:06:41 -04:00
FFormatNamedArguments Args ;
2020-08-11 01:36:57 -04:00
Args . Add ( TEXT ( " LayerName " ) , FText : : FromName ( Layer - > GetLayerName ( ) ) ) ;
2014-04-23 18:06:41 -04:00
2014-03-14 14:13:41 -04:00
if ( ! Actor . IsValid ( ) )
{
2014-04-23 18:06:41 -04:00
OutMessage = FText : : Format ( LOCTEXT ( " InvalidActor " , " Cannot add invalid Actors to {LayerName} " ) , Args ) ;
2014-03-14 14:13:41 -04:00
return false ;
}
2014-04-23 18:06:41 -04:00
Args . Add ( TEXT ( " ActorName " ) , FText : : FromName ( Actor - > GetFName ( ) ) ) ;
2019-09-10 11:35:20 -04:00
if ( ! WorldLayers - > IsActorValidForLayer ( Actor . Get ( ) ) )
2014-03-14 14:13:41 -04:00
{
2014-04-23 18:06:41 -04:00
OutMessage = FText : : Format ( LOCTEXT ( " InvalidLayers " , " Actor '{ActorName}' cannot be associated with Layers " ) , Args ) ;
2014-03-14 14:13:41 -04:00
return false ;
}
2020-08-11 01:36:57 -04:00
if ( Actor - > Layers . Contains ( Layer - > GetLayerName ( ) ) )
2014-03-14 14:13:41 -04:00
{
2014-04-23 18:06:41 -04:00
OutMessage = FText : : Format ( LOCTEXT ( " AlreadyAssignedActor " , " Already assigned to {LayerName} " ) , Args ) ;
2014-03-14 14:13:41 -04:00
return false ;
}
2014-04-23 18:06:41 -04:00
OutMessage = FText : : Format ( LOCTEXT ( " AssignActor " , " Assign to {LayerName} " ) , Args ) ;
2014-03-14 14:13:41 -04:00
return true ;
}
void FLayerViewModel : : AppendActors ( TArray < TWeakObjectPtr < AActor > > & InActors ) const
{
if ( ! Layer . IsValid ( ) )
{
return ;
}
2020-08-11 01:36:57 -04:00
WorldLayers - > AppendActorsFromLayer ( Layer - > GetLayerName ( ) , InActors ) ;
2014-03-14 14:13:41 -04:00
}
void FLayerViewModel : : AppendActorsOfSpecificType ( TArray < TWeakObjectPtr < AActor > > & InActors , const TWeakObjectPtr < UClass > & Class )
{
if ( ! Layer . IsValid ( ) )
{
return ;
}
struct Local
{
2014-03-15 01:14:25 -04:00
static bool ActorIsOfClass ( const TWeakObjectPtr < AActor > & Actor , const TWeakObjectPtr < UClass > InClass )
2014-03-14 14:13:41 -04:00
{
2014-03-15 01:14:25 -04:00
return Actor - > GetClass ( ) = = InClass . Get ( ) ;
2014-03-14 14:13:41 -04:00
}
} ;
TSharedRef < TDelegateFilter < const TWeakObjectPtr < AActor > & > > Filter = MakeShareable ( new TDelegateFilter < const TWeakObjectPtr < AActor > & > ( TDelegateFilter < const TWeakObjectPtr < AActor > & > : : FPredicate : : CreateStatic ( & Local : : ActorIsOfClass , Class ) ) ) ;
2020-08-11 01:36:57 -04:00
WorldLayers - > AppendActorsFromLayer ( Layer - > GetLayerName ( ) , InActors , Filter ) ;
2014-03-14 14:13:41 -04:00
}
void FLayerViewModel : : AddActor ( const TWeakObjectPtr < AActor > & Actor )
{
if ( ! Layer . IsValid ( ) )
{
return ;
}
const FScopedTransaction Transaction ( LOCTEXT ( " AddActor " , " Add Actor to Layer " ) ) ;
2020-08-11 01:36:57 -04:00
WorldLayers - > AddActorToLayer ( Actor . Get ( ) , Layer - > GetLayerName ( ) ) ;
2014-03-14 14:13:41 -04:00
}
void FLayerViewModel : : AddActors ( const TArray < TWeakObjectPtr < AActor > > & Actors )
{
if ( ! Layer . IsValid ( ) )
{
return ;
}
const FScopedTransaction Transaction ( LOCTEXT ( " AddActors " , " Add Actors to Layer " ) ) ;
2020-08-11 01:36:57 -04:00
WorldLayers - > AddActorsToLayer ( Actors , Layer - > GetLayerName ( ) ) ;
2014-03-14 14:13:41 -04:00
}
void FLayerViewModel : : RemoveActors ( const TArray < TWeakObjectPtr < AActor > > & Actors )
{
if ( ! Layer . IsValid ( ) )
{
return ;
}
const FScopedTransaction Transaction ( LOCTEXT ( " RemoveActors " , " Remove Actors from Layer " ) ) ;
2020-08-11 01:36:57 -04:00
WorldLayers - > RemoveActorsFromLayer ( Actors , Layer - > GetLayerName ( ) ) ;
2014-03-14 14:13:41 -04:00
}
void FLayerViewModel : : RemoveActor ( const TWeakObjectPtr < AActor > & Actor )
{
if ( ! Layer . IsValid ( ) )
{
return ;
}
const FScopedTransaction Transaction ( LOCTEXT ( " RemoveActor " , " Remove Actor from Layer " ) ) ;
2020-08-11 01:36:57 -04:00
WorldLayers - > RemoveActorFromLayer ( Actor . Get ( ) , Layer - > GetLayerName ( ) ) ;
2014-03-14 14:13:41 -04:00
}
void FLayerViewModel : : SelectActors ( bool bSelect , bool bNotify , bool bSelectEvenIfHidden , const TSharedPtr < IFilter < const TWeakObjectPtr < AActor > & > > & Filter )
{
if ( ! Layer . IsValid ( ) )
{
return ;
}
const FScopedTransaction Transaction ( LOCTEXT ( " SelectActors " , " Select Actors in Layer " ) ) ;
const bool bNotifySelectNone = false ;
const bool bDeselectBSPSurfs = true ;
Editor - > SelectNone ( bNotifySelectNone , bDeselectBSPSurfs ) ;
2020-08-11 01:36:57 -04:00
WorldLayers - > SelectActorsInLayer ( Layer - > GetLayerName ( ) , bSelect , bNotify , bSelectEvenIfHidden , Filter ) ;
2014-03-14 14:13:41 -04:00
}
2015-01-07 09:52:40 -05:00
FText FLayerViewModel : : GetActorStatTotal ( int32 StatsIndex ) const
2014-03-14 14:13:41 -04:00
{
if ( ! Layer . IsValid ( ) )
{
2015-01-07 09:52:40 -05:00
return FText : : AsNumber ( 0 ) ;
2014-03-14 14:13:41 -04:00
}
if ( ActorStats . Num ( ) < = StatsIndex )
{
2015-01-07 09:52:40 -05:00
return LOCTEXT ( " InvalidActorStatTotal " , " Invalid " ) ;
2014-03-14 14:13:41 -04:00
}
2015-01-07 09:52:40 -05:00
return FText : : AsNumber ( ActorStats [ StatsIndex ] . Total ) ;
2014-03-14 14:13:41 -04:00
}
void FLayerViewModel : : SelectActorsOfSpecificType ( const TWeakObjectPtr < UClass > & Class )
{
if ( ! Layer . IsValid ( ) )
{
return ;
}
struct Local
{
2014-06-05 12:16:00 -04:00
static bool ActorIsOfClass ( const TWeakObjectPtr < AActor > & Actor , const TWeakObjectPtr < UClass > InClass )
2014-03-14 14:13:41 -04:00
{
2014-06-05 12:16:00 -04:00
return Actor - > GetClass ( ) = = InClass . Get ( ) ;
2014-03-14 14:13:41 -04:00
}
} ;
const bool bSelect = true ;
const bool bNotify = true ;
const bool bSelectEvenIfHidden = true ;
TSharedRef < TDelegateFilter < const TWeakObjectPtr < AActor > & > > Filter = MakeShareable ( new TDelegateFilter < const TWeakObjectPtr < AActor > & > ( TDelegateFilter < const TWeakObjectPtr < AActor > & > : : FPredicate : : CreateStatic ( & Local : : ActorIsOfClass , Class ) ) ) ;
SelectActors ( bSelect , bNotify , bSelectEvenIfHidden , Filter ) ;
}
const TArray < FLayerActorStats > & FLayerViewModel : : GetActorStats ( ) const
{
return ActorStats ;
}
void FLayerViewModel : : SetDataSource ( const TWeakObjectPtr < ULayer > & InLayer )
{
if ( Layer = = InLayer )
{
return ;
}
Layer = InLayer ;
Refresh ( ) ;
}
const TWeakObjectPtr < ULayer > FLayerViewModel : : GetDataSource ( )
{
return Layer ;
}
void FLayerViewModel : : OnLayersChanged ( const ELayersAction : : Type Action , const TWeakObjectPtr < ULayer > & ChangedLayer , const FName & ChangedProperty )
{
if ( Action ! = ELayersAction : : Modify & & Action ! = ELayersAction : : Reset )
{
return ;
}
if ( ChangedLayer . IsValid ( ) & & ChangedLayer ! = Layer )
{
return ;
}
if ( Action = = ELayersAction : : Reset | | ChangedProperty = = TEXT ( " ActorStats " ) )
{
RefreshActorStats ( ) ;
}
ChangedEvent . Broadcast ( ) ;
}
void FLayerViewModel : : RefreshActorStats ( )
{
ActorStats . Empty ( ) ;
if ( ! Layer . IsValid ( ) )
{
return ;
}
2020-08-11 01:36:57 -04:00
ActorStats . Append ( Layer - > GetActorStats ( ) ) ;
2014-03-14 14:13:41 -04:00
struct FCompareLayerActorStats
{
FORCEINLINE bool operator ( ) ( const FLayerActorStats & Lhs , const FLayerActorStats & Rhs ) const
{
int32 Result = Lhs . Type - > GetFName ( ) . Compare ( Rhs . Type - > GetFName ( ) ) ;
return Result > 0 ;
}
} ;
ActorStats . Sort ( FCompareLayerActorStats ( ) ) ;
}
void FLayerViewModel : : Refresh ( )
{
OnLayersChanged ( ELayersAction : : Reset , NULL , NAME_None ) ;
}
# undef LOCTEXT_NAMESPACE