2020-10-28 06:51:40 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
# include "DataLayerMode.h"
# include "SSceneOutliner.h"
# include "SDataLayerBrowser.h"
# include "DataLayer/DataLayerEditorSubsystem.h"
2021-05-18 13:18:48 -04:00
# include "WorldPartition/DataLayer/WorldDataLayers.h"
2020-10-28 06:51:40 -04:00
# include "DataLayerHierarchy.h"
# include "DataLayerActorTreeItem.h"
# include "DataLayerTreeItem.h"
# include "DataLayerDragDropOp.h"
# include "ISceneOutlinerHierarchy.h"
# include "SceneOutlinerMenuContext.h"
# include "ScopedTransaction.h"
# include "DragAndDrop/ActorDragDropOp.h"
# include "DragAndDrop/FolderDragDropOp.h"
2021-01-25 16:15:52 -04:00
# include "ActorMode.h"
2021-05-04 17:24:35 -04:00
# include "DataLayersActorDescTreeItem.h"
2020-10-28 06:51:40 -04:00
# include "EditorActorFolders.h"
# include "Algo/Transform.h"
# include "ToolMenus.h"
2020-10-28 07:24:36 -04:00
# include "Selection.h"
2020-10-28 06:51:40 -04:00
# include "Editor.h"
# define LOCTEXT_NAMESPACE "DataLayer"
FDataLayerModeParams : : FDataLayerModeParams ( SSceneOutliner * InSceneOutliner , SDataLayerBrowser * InDataLayerBrowser , const TWeakObjectPtr < UWorld > & InSpecifiedWorldToDisplay )
: SpecifiedWorldToDisplay ( InSpecifiedWorldToDisplay )
, DataLayerBrowser ( InDataLayerBrowser )
, SceneOutliner ( InSceneOutliner )
{ }
FDataLayerMode : : FDataLayerMode ( const FDataLayerModeParams & Params )
: ISceneOutlinerMode ( Params . SceneOutliner )
, DataLayerBrowser ( Params . DataLayerBrowser )
, SpecifiedWorldToDisplay ( Params . SpecifiedWorldToDisplay )
{
2021-01-25 16:15:52 -04:00
SceneOutliner - > AddFilter ( MakeShared < TSceneOutlinerPredicateFilter < FDataLayerActorTreeItem > > ( FDataLayerActorTreeItem : : FFilterPredicate : : CreateLambda ( [ this ] ( const AActor * Actor , const UDataLayer * DataLayer )
{
return FActorMode : : IsActorDisplayable ( SceneOutliner , Actor ) ;
} ) , FSceneOutlinerFilter : : EDefaultBehaviour : : Pass ) ) ;
2020-10-28 06:51:40 -04:00
DataLayerEditorSubsystem = UDataLayerEditorSubsystem : : Get ( ) ;
Rebuild ( ) ;
const_cast < FSharedSceneOutlinerData & > ( SceneOutliner - > GetSharedData ( ) ) . CustomDelete = FCustomSceneOutlinerDeleteDelegate : : CreateRaw ( this , & FDataLayerMode : : DeleteItems ) ;
}
int32 FDataLayerMode : : GetTypeSortPriority ( const ISceneOutlinerTreeItem & Item ) const
{
if ( Item . IsA < FDataLayerTreeItem > ( ) )
{
2021-05-04 17:24:35 -04:00
return static_cast < int32 > ( EItemSortOrder : : DataLayer ) ;
2020-10-28 06:51:40 -04:00
}
else if ( Item . IsA < FDataLayerActorTreeItem > ( ) )
{
2021-05-04 17:24:35 -04:00
return static_cast < int32 > ( EItemSortOrder : : Actor ) ;
}
else if ( Item . IsA < FDataLayerActorDescTreeItem > ( ) )
{
return static_cast < int32_t > ( EItemSortOrder : : Unloaded ) ;
2020-10-28 06:51:40 -04:00
}
// Warning: using actor mode with an unsupported item type!
check ( false ) ;
return - 1 ;
}
2021-02-09 15:01:37 -04:00
bool FDataLayerMode : : CanRenameItem ( const ISceneOutlinerTreeItem & Item ) const
{
if ( Item . IsValid ( ) & & ( Item . IsA < FDataLayerTreeItem > ( ) ) )
{
FDataLayerTreeItem * DataLayerTreeItem = ( FDataLayerTreeItem * ) & Item ;
return ! DataLayerTreeItem - > GetDataLayer ( ) - > IsLocked ( ) ;
}
return false ;
}
2021-01-27 13:03:11 -04:00
FText FDataLayerMode : : GetStatusText ( ) const
{
if ( SelectedDataLayersSet . Num ( ) = = 1 )
{
if ( const UDataLayer * DataLayer = SelectedDataLayersSet . Array ( ) [ 0 ] . Get ( ) )
{
return FText : : FromName ( DataLayer - > GetDataLayerLabel ( ) ) ;
}
}
else if ( SelectedDataLayersSet . Num ( ) > 1 )
{
return FText : : Format ( LOCTEXT ( " DetailsMultipleDataLayersSelected " , " {0} Data Layers Selected " ) , FText : : AsNumber ( SelectedDataLayersSet . Num ( ) ) ) ;
}
return LOCTEXT ( " DetailsNoDataLayerSelected " , " No Data Layer Selected " ) ;
}
2020-10-28 06:51:40 -04:00
SDataLayerBrowser * FDataLayerMode : : GetDataLayerBrowser ( ) const
{
return DataLayerBrowser ;
}
void FDataLayerMode : : OnItemAdded ( FSceneOutlinerTreeItemPtr Item )
{
if ( const FDataLayerTreeItem * DataLayerItem = Item - > CastTo < FDataLayerTreeItem > ( ) )
{
if ( ! Item - > Flags . bIsFilteredOut )
{
2020-11-03 18:28:22 -04:00
if ( SelectedDataLayersSet . Contains ( DataLayerItem - > GetDataLayer ( ) ) )
2020-11-03 17:16:48 -04:00
{
SceneOutliner - > AddToSelection ( { Item } ) ;
}
}
}
else if ( const FDataLayerActorTreeItem * DataLayerActorTreeItem = Item - > CastTo < FDataLayerActorTreeItem > ( ) )
{
if ( SelectedDataLayerActors . Contains ( FSelectedDataLayerActor ( DataLayerActorTreeItem - > GetDataLayer ( ) , DataLayerActorTreeItem - > GetActor ( ) ) ) )
{
SceneOutliner - > AddToSelection ( { Item } ) ;
2020-10-28 06:51:40 -04:00
}
}
}
void FDataLayerMode : : OnItemDoubleClick ( FSceneOutlinerTreeItemPtr Item )
{
if ( const FDataLayerTreeItem * DataLayerItem = Item - > CastTo < FDataLayerTreeItem > ( ) )
{
2020-12-03 12:41:42 -04:00
if ( UDataLayer * DataLayer = DataLayerItem - > GetDataLayer ( ) )
2020-10-28 06:51:40 -04:00
{
2021-03-17 15:17:35 -04:00
const FScopedTransaction Transaction ( LOCTEXT ( " SelectActorsInDataLayer " , " Select Actors in Data Layer " ) ) ;
2020-10-28 06:51:40 -04:00
GEditor - > SelectNone ( /*bNoteSelectionChange*/ false , true ) ;
DataLayerEditorSubsystem - > SelectActorsInDataLayer ( DataLayer , /*bSelect*/ true , /*bNotify*/ true , /*bSelectEvenIfHidden*/ true ) ;
}
}
else if ( FDataLayerActorTreeItem * DataLayerActorItem = Item - > CastTo < FDataLayerActorTreeItem > ( ) )
{
if ( AActor * Actor = DataLayerActorItem - > GetActor ( ) )
{
2021-03-17 15:17:35 -04:00
const FScopedTransaction Transaction ( LOCTEXT ( " ClickingOnActor " , " Clicking on Actor in Data Layer " ) ) ;
2020-10-28 06:51:40 -04:00
GEditor - > GetSelectedActors ( ) - > Modify ( ) ;
GEditor - > SelectNone ( /*bNoteSelectionChange*/ false , true ) ;
GEditor - > SelectActor ( Actor , /*bSelected*/ true , /*bNotify*/ true , /*bSelectEvenIfHidden*/ true ) ;
GEditor - > NoteSelectionChange ( ) ;
GEditor - > MoveViewportCamerasToActor ( * Actor , /*bActiveViewportOnly*/ false ) ;
}
}
}
void FDataLayerMode : : DeleteItems ( const TArray < TWeakPtr < ISceneOutlinerTreeItem > > & Items )
{
2020-12-03 12:41:42 -04:00
TArray < UDataLayer * > DataLayersToDelete ;
TMap < UDataLayer * , TArray < AActor * > > ActorsToRemoveFromDataLayer ;
2020-10-28 06:51:40 -04:00
for ( const TWeakPtr < ISceneOutlinerTreeItem > & Item : Items )
{
if ( FDataLayerActorTreeItem * DataLayerActorItem = Item . Pin ( ) - > CastTo < FDataLayerActorTreeItem > ( ) )
{
2020-12-03 12:41:42 -04:00
UDataLayer * DataLayer = DataLayerActorItem - > GetDataLayer ( ) ;
2020-10-28 06:51:40 -04:00
AActor * Actor = DataLayerActorItem - > GetActor ( ) ;
2021-02-09 15:01:37 -04:00
if ( DataLayer & & ! DataLayer - > IsLocked ( ) & & Actor )
2020-10-28 06:51:40 -04:00
{
ActorsToRemoveFromDataLayer . FindOrAdd ( DataLayer ) . Add ( Actor ) ;
}
}
else if ( FDataLayerTreeItem * DataLayerItem = Item . Pin ( ) - > CastTo < FDataLayerTreeItem > ( ) )
{
if ( UDataLayer * DataLayer = DataLayerItem - > GetDataLayer ( ) )
{
2021-02-09 15:01:37 -04:00
if ( ! DataLayer - > IsLocked ( ) )
{
DataLayersToDelete . Add ( DataLayer ) ;
}
2020-10-28 06:51:40 -04:00
}
}
}
if ( ! ActorsToRemoveFromDataLayer . IsEmpty ( ) )
{
const FScopedTransaction Transaction ( LOCTEXT ( " RemoveActorsFromDataLayer " , " Remove Actors from Data Layer " ) ) ;
for ( const auto & ItPair : ActorsToRemoveFromDataLayer )
{
DataLayerEditorSubsystem - > RemoveActorsFromDataLayer ( ItPair . Value , ItPair . Key ) ;
}
}
else if ( ! DataLayersToDelete . IsEmpty ( ) )
{
2021-01-27 13:03:11 -04:00
int32 PrevDeleteCount = SelectedDataLayersSet . Num ( ) ;
for ( UDataLayer * DataLayerToDelete : DataLayersToDelete )
{
SelectedDataLayersSet . Remove ( DataLayerToDelete ) ;
}
{
2021-03-17 15:17:35 -04:00
const FScopedTransaction Transaction ( LOCTEXT ( " DeleteDataLayers " , " Delete Data Layers " ) ) ;
2021-01-27 13:03:11 -04:00
DataLayerEditorSubsystem - > DeleteDataLayers ( DataLayersToDelete ) ;
}
if ( ( SelectedDataLayersSet . Num ( ) ! = PrevDeleteCount ) & & DataLayerBrowser )
{
DataLayerBrowser - > OnSelectionChanged ( SelectedDataLayersSet ) ;
}
2020-10-28 06:51:40 -04:00
}
}
FReply FDataLayerMode : : OnKeyDown ( const FKeyEvent & InKeyEvent )
{
const FSceneOutlinerItemSelection & Selection = SceneOutliner - > GetSelection ( ) ;
// Rename key: Rename selected actors (not rebindable, because it doesn't make much sense to bind.)
if ( InKeyEvent . GetKey ( ) = = EKeys : : F2 )
{
if ( Selection . Num ( ) = = 1 )
{
FSceneOutlinerTreeItemPtr ItemToRename = Selection . SelectedItems [ 0 ] . Pin ( ) ;
if ( ItemToRename . IsValid ( ) & & CanRenameItem ( * ItemToRename ) & & ItemToRename - > CanInteract ( ) )
{
SceneOutliner - > SetPendingRenameItem ( ItemToRename ) ;
SceneOutliner - > ScrollItemIntoView ( ItemToRename ) ;
}
return FReply : : Handled ( ) ;
}
}
// F5 forces a full refresh
else if ( InKeyEvent . GetKey ( ) = = EKeys : : F5 )
{
SceneOutliner - > FullRefresh ( ) ;
return FReply : : Handled ( ) ;
}
// Delete/BackSpace keys delete selected actors
else if ( InKeyEvent . GetKey ( ) = = EKeys : : Delete | | InKeyEvent . GetKey ( ) = = EKeys : : BackSpace )
{
DeleteItems ( Selection . SelectedItems ) ;
return FReply : : Handled ( ) ;
}
return FReply : : Unhandled ( ) ;
}
bool FDataLayerMode : : ParseDragDrop ( FSceneOutlinerDragDropPayload & OutPayload , const FDragDropOperation & Operation ) const
{
return ! GetActorsFromOperation ( Operation , true ) . IsEmpty ( ) ;
}
FSceneOutlinerDragValidationInfo FDataLayerMode : : ValidateDrop ( const ISceneOutlinerTreeItem & DropTarget , const FSceneOutlinerDragDropPayload & Payload ) const
{
2021-02-10 19:52:02 -04:00
TArray < AActor * > PayloadActors = GetActorsFromOperation ( Payload . SourceOperation ) ;
2020-10-28 06:51:40 -04:00
if ( ! PayloadActors . IsEmpty ( ) )
{
2021-02-10 19:51:47 -04:00
for ( AActor * Actor : PayloadActors )
{
if ( ! Actor - > SupportsDataLayer ( ) )
{
return FSceneOutlinerDragValidationInfo ( ESceneOutlinerDropCompatibility : : IncompatibleGeneric , LOCTEXT ( " ActorCantBeAssignedToDataLayer " , " Can't assign actors to Data Layer " ) ) ;
}
}
2020-10-28 06:51:40 -04:00
if ( const FDataLayerTreeItem * DataLayerItem = DropTarget . CastTo < FDataLayerTreeItem > ( ) )
{
const UDataLayer * DataLayerTarget = DataLayerItem - > GetDataLayer ( ) ;
if ( ! DataLayerTarget )
{
return FSceneOutlinerDragValidationInfo ( ESceneOutlinerDropCompatibility : : IncompatibleGeneric , FText ( ) ) ;
}
2021-02-09 15:01:37 -04:00
if ( DataLayerTarget - > IsLocked ( ) )
2020-11-03 17:16:48 -04:00
{
2021-02-10 19:51:47 -04:00
return FSceneOutlinerDragValidationInfo ( ESceneOutlinerDropCompatibility : : IncompatibleGeneric , LOCTEXT ( " CantReassignLockedDataLayer " , " Can't reassign actors from locked Data Layer " ) ) ;
2020-11-03 17:16:48 -04:00
}
2021-02-09 15:01:37 -04:00
if ( GetSelectedDataLayers ( SceneOutliner ) . Num ( ) > 1 )
{
TArray < UDataLayer * > SelectedDataLayers = GetSelectedDataLayers ( SceneOutliner ) ;
for ( UDataLayer * SelectedDataLayer : SelectedDataLayers )
{
if ( SelectedDataLayer - > IsLocked ( ) )
{
2021-02-10 19:51:47 -04:00
return FSceneOutlinerDragValidationInfo ( ESceneOutlinerDropCompatibility : : IncompatibleGeneric , LOCTEXT ( " CantReassignLockedDataLayer " , " Can't reassign actors from locked Data Layer " ) ) ;
2021-02-09 15:01:37 -04:00
}
}
if ( SceneOutliner - > GetTree ( ) . IsItemSelected ( const_cast < ISceneOutlinerTreeItem & > ( DropTarget ) . AsShared ( ) ) )
{
return FSceneOutlinerDragValidationInfo ( ESceneOutlinerDropCompatibility : : Compatible , LOCTEXT ( " AssignToDataLayers " , " Assign to Selected Data Layers " ) ) ;
}
}
2020-10-28 06:51:40 -04:00
return FSceneOutlinerDragValidationInfo ( ESceneOutlinerDropCompatibility : : Compatible , FText : : Format ( LOCTEXT ( " AssignToDataLayer " , " Assign to Data Layer \" {0} \" " ) , FText : : FromName ( DataLayerTarget - > GetDataLayerLabel ( ) ) ) ) ;
}
}
return FSceneOutlinerDragValidationInfo : : Invalid ( ) ;
}
TArray < AActor * > FDataLayerMode : : GetActorsFromOperation ( const FDragDropOperation & Operation , bool bOnlyFindFirst ) const
{
TSet < AActor * > Actors ;
auto GetActorsFromFolderOperation = [ & Actors , bOnlyFindFirst ] ( const FFolderDragDropOp & FolderOp )
{
if ( bOnlyFindFirst & & Actors . Num ( ) )
{
return ;
}
if ( UWorld * World = FolderOp . World . Get ( ) )
{
TArray < TWeakObjectPtr < AActor > > ActorsToDrop ;
FActorFolders : : GetWeakActorsFromFolders ( * World , FolderOp . Folders , ActorsToDrop ) ;
for ( const auto & Actor : ActorsToDrop )
{
if ( AActor * ActorPtr = Actor . Get ( ) )
{
Actors . Add ( ActorPtr ) ;
if ( bOnlyFindFirst )
{
break ;
}
}
}
}
} ;
auto GetActorsFromActorOperation = [ & Actors , bOnlyFindFirst ] ( const FActorDragDropOp & ActorOp )
{
if ( bOnlyFindFirst & & Actors . Num ( ) )
{
return ;
}
for ( const auto & Actor : ActorOp . Actors )
{
if ( AActor * ActorPtr = Actor . Get ( ) )
{
Actors . Add ( ActorPtr ) ;
if ( bOnlyFindFirst )
{
break ;
}
}
}
} ;
2021-02-08 17:38:18 -04:00
if ( Operation . IsOfType < FActorDragDropOp > ( ) )
2020-10-28 06:51:40 -04:00
{
2021-02-08 17:38:18 -04:00
const FActorDragDropOp & ActorDragOp = StaticCast < const FActorDragDropOp & > ( Operation ) ;
GetActorsFromActorOperation ( ActorDragOp ) ;
2020-10-28 06:51:40 -04:00
}
2021-02-08 17:38:18 -04:00
if ( Operation . IsOfType < FFolderDragDropOp > ( ) )
2020-10-28 06:51:40 -04:00
{
2021-02-08 17:38:18 -04:00
const FFolderDragDropOp & FolderDragOp = StaticCast < const FFolderDragDropOp & > ( Operation ) ;
GetActorsFromFolderOperation ( FolderDragOp ) ;
}
if ( Operation . IsOfType < FCompositeDragDropOp > ( ) )
{
const FCompositeDragDropOp & CompositeDragOp = StaticCast < const FCompositeDragDropOp & > ( Operation ) ;
if ( TSharedPtr < const FActorDragDropOp > ActorSubOp = CompositeDragOp . GetSubOp < FActorDragDropOp > ( ) )
{
GetActorsFromActorOperation ( * ActorSubOp ) ;
}
if ( TSharedPtr < const FFolderDragDropOp > FolderSubOp = CompositeDragOp . GetSubOp < FFolderDragDropOp > ( ) )
{
GetActorsFromFolderOperation ( * FolderSubOp ) ;
}
2020-10-28 06:51:40 -04:00
}
return Actors . Array ( ) ;
}
void FDataLayerMode : : OnDrop ( ISceneOutlinerTreeItem & DropTarget , const FSceneOutlinerDragDropPayload & Payload , const FSceneOutlinerDragValidationInfo & ValidationInfo ) const
{
2020-11-03 17:16:48 -04:00
TArray < AActor * > ActorsToAdd = GetActorsFromOperation ( Payload . SourceOperation ) ;
if ( ActorsToAdd . IsEmpty ( ) )
2020-10-28 06:51:40 -04:00
{
return ;
}
if ( const FDataLayerTreeItem * DataLayerItem = DropTarget . CastTo < FDataLayerTreeItem > ( ) )
{
2020-12-03 12:41:42 -04:00
if ( UDataLayer * DataLayer = DataLayerItem - > GetDataLayer ( ) )
2020-10-28 06:51:40 -04:00
{
2020-11-03 17:16:48 -04:00
if ( SceneOutliner - > GetTree ( ) . IsItemSelected ( const_cast < ISceneOutlinerTreeItem & > ( DropTarget ) . AsShared ( ) ) )
{
2020-12-03 12:41:42 -04:00
TArray < UDataLayer * > AllSelectedDataLayers = GetSelectedDataLayers ( SceneOutliner ) ;
2020-11-03 17:16:48 -04:00
if ( AllSelectedDataLayers . Num ( ) > 1 )
{
2021-03-17 15:17:35 -04:00
const FScopedTransaction Transaction ( LOCTEXT ( " DataLayerOutlinerAddActorsToDataLayers " , " Add Actors to Data Layers " ) ) ;
2020-11-03 17:16:48 -04:00
DataLayerEditorSubsystem - > AddActorsToDataLayers ( ActorsToAdd , AllSelectedDataLayers ) ;
return ;
}
}
2021-03-17 15:17:35 -04:00
const FScopedTransaction Transaction ( LOCTEXT ( " DataLayerOutlinerAddActorsToDataLayer " , " Add Actors to Data Layer " ) ) ;
2020-11-03 17:16:48 -04:00
DataLayerEditorSubsystem - > AddActorsToDataLayer ( ActorsToAdd , DataLayer ) ;
2020-10-28 06:51:40 -04:00
}
}
}
struct FWeakDataLayerActorSelector
{
bool operator ( ) ( const TWeakPtr < ISceneOutlinerTreeItem > & Item , TWeakObjectPtr < AActor > & DataOut ) const
{
if ( TSharedPtr < ISceneOutlinerTreeItem > ItemPtr = Item . Pin ( ) )
{
if ( FDataLayerActorTreeItem * TypedItem = ItemPtr - > CastTo < FDataLayerActorTreeItem > ( ) )
{
if ( TypedItem - > IsValid ( ) )
{
DataOut = TypedItem - > Actor ;
return true ;
}
}
}
return false ;
}
} ;
struct FWeakDataLayerSelector
{
bool operator ( ) ( const TWeakPtr < ISceneOutlinerTreeItem > & Item , TWeakObjectPtr < UDataLayer > & DataOut ) const
{
if ( TSharedPtr < ISceneOutlinerTreeItem > ItemPtr = Item . Pin ( ) )
{
if ( FDataLayerTreeItem * TypedItem = ItemPtr - > CastTo < FDataLayerTreeItem > ( ) )
{
if ( TypedItem - > IsValid ( ) )
{
DataOut = TypedItem - > GetDataLayer ( ) ;
return true ;
}
}
}
return false ;
}
} ;
TSharedPtr < FDragDropOperation > FDataLayerMode : : CreateDragDropOperation ( const TArray < FSceneOutlinerTreeItemPtr > & InTreeItems ) const
{
FSceneOutlinerDragDropPayload DraggedObjects ( InTreeItems ) ;
TSharedPtr < FSceneOutlinerDragDropOp > OutlinerOp = MakeShareable ( new FSceneOutlinerDragDropOp ( ) ) ;
if ( DraggedObjects . Has < FDataLayerActorTreeItem > ( ) )
{
TSharedPtr < FActorDragDropOp > ActorOperation = MakeShareable ( new FActorDragDropOp ) ;
ActorOperation - > Init ( DraggedObjects . GetData < TWeakObjectPtr < AActor > > ( FWeakDataLayerActorSelector ( ) ) ) ;
OutlinerOp - > AddSubOp ( ActorOperation ) ;
}
if ( DraggedObjects . Has < FDataLayerTreeItem > ( ) )
{
TSharedPtr < FDataLayerDragDropOp > DataLayerOperation = MakeShareable ( new FDataLayerDragDropOp ) ;
TArray < TWeakObjectPtr < UDataLayer > > DataLayers = DraggedObjects . GetData < TWeakObjectPtr < UDataLayer > > ( FWeakDataLayerSelector ( ) ) ;
for ( const auto & DataLayer : DataLayers )
{
if ( DataLayer . IsValid ( ) )
{
DataLayerOperation - > DataLayerLabels . Add ( DataLayer - > GetDataLayerLabel ( ) ) ;
}
}
DataLayerOperation - > Construct ( ) ;
OutlinerOp - > AddSubOp ( DataLayerOperation ) ;
}
OutlinerOp - > Construct ( ) ;
return OutlinerOp ;
}
static const FName DefaultContextBaseMenuName ( " DataLayerOutliner.DefaultContextMenuBase " ) ;
static const FName DefaultContextMenuName ( " DataLayerOutliner.DefaultContextMenu " ) ;
2020-12-03 12:41:42 -04:00
TArray < UDataLayer * > FDataLayerMode : : GetSelectedDataLayers ( SSceneOutliner * InSceneOutliner ) const
2020-11-03 17:16:48 -04:00
{
FSceneOutlinerItemSelection ItemSelection ( InSceneOutliner - > GetSelection ( ) ) ;
TArray < FDataLayerTreeItem * > SelectedDataLayerItems ;
ItemSelection . Get < FDataLayerTreeItem > ( SelectedDataLayerItems ) ;
2020-12-03 12:41:42 -04:00
TArray < UDataLayer * > ValidSelectedDataLayers ;
2020-11-03 17:16:48 -04:00
Algo : : TransformIf ( SelectedDataLayerItems , ValidSelectedDataLayers , [ ] ( const auto Item ) { return Item & & Item - > GetDataLayer ( ) ; } , [ ] ( const auto Item ) { return Item - > GetDataLayer ( ) ; } ) ;
return MoveTemp ( ValidSelectedDataLayers ) ;
}
2020-10-28 06:51:40 -04:00
void FDataLayerMode : : RegisterContextMenu ( )
{
UToolMenus * ToolMenus = UToolMenus : : Get ( ) ;
if ( ! ToolMenus - > IsMenuRegistered ( DefaultContextBaseMenuName ) )
{
UToolMenu * Menu = ToolMenus - > RegisterMenu ( DefaultContextBaseMenuName ) ;
Menu - > AddDynamicSection ( " DataLayerDynamicSection " , FNewToolMenuDelegate : : CreateLambda ( [ this ] ( UToolMenu * InMenu )
{
USceneOutlinerMenuContext * Context = InMenu - > FindContext < USceneOutlinerMenuContext > ( ) ;
if ( ! Context | | ! Context - > SceneOutliner . IsValid ( ) )
{
return ;
}
SSceneOutliner * SceneOutliner = Context - > SceneOutliner . Pin ( ) . Get ( ) ;
2020-12-03 12:41:42 -04:00
TArray < UDataLayer * > SelectedDataLayers = GetSelectedDataLayers ( SceneOutliner ) ;
2020-10-28 06:51:40 -04:00
TArray < const UDataLayer * > AllDataLayers ;
2021-05-03 09:39:35 -04:00
if ( const AWorldDataLayers * WorldDataLayers = RepresentingWorld . Get ( ) - > GetWorldDataLayers ( ) )
2020-10-28 06:51:40 -04:00
{
WorldDataLayers - > ForEachDataLayer ( [ & AllDataLayers ] ( UDataLayer * DataLayer )
2020-11-03 17:16:48 -04:00
{
AllDataLayers . Add ( DataLayer ) ;
return true ;
} ) ;
2020-10-28 06:51:40 -04:00
}
{
2021-03-17 15:17:35 -04:00
FToolMenuSection & Section = InMenu - > AddSection ( " DataLayers " , LOCTEXT ( " DataLayers " , " Data Layers " ) ) ;
Section . AddMenuEntry ( " CreateEmptyDataLayer " , LOCTEXT ( " CreateEmptyDataLayer " , " Create Empty Data Layer " ) , FText ( ) , FSlateIcon ( ) ,
2020-10-28 06:51:40 -04:00
FUIAction (
FExecuteAction : : CreateLambda ( [ = ] ( ) {
2021-03-17 15:17:35 -04:00
const FScopedTransaction Transaction ( LOCTEXT ( " CreateEmptyDataLayer " , " Create Empty Data Layer " ) ) ;
2020-10-28 06:51:40 -04:00
DataLayerEditorSubsystem - > CreateDataLayer ( ) ;
} )
) ) ;
2021-03-17 15:17:35 -04:00
Section . AddMenuEntry ( " AddSelectedActorsToNewDataLayer " , LOCTEXT ( " AddSelectedActorsToNewDataLayer " , " Add Selected Actors to New Data Layer " ) , FText ( ) , FSlateIcon ( ) ,
2020-10-28 06:51:40 -04:00
FUIAction (
FExecuteAction : : CreateLambda ( [ = ] ( ) {
2021-03-17 15:17:35 -04:00
const FScopedTransaction Transaction ( LOCTEXT ( " AddSelectedActorsToNewDataLayer " , " Add Selected Actors to New Data Layer " ) ) ;
2020-10-28 06:51:40 -04:00
if ( UDataLayer * NewDataLayer = DataLayerEditorSubsystem - > CreateDataLayer ( ) )
{
DataLayerEditorSubsystem - > AddSelectedActorsToDataLayer ( NewDataLayer ) ;
} } ) ,
FCanExecuteAction : : CreateLambda ( [ = ] { return GEditor - > GetSelectedActorCount ( ) > 0 ; } )
2020-12-03 12:41:42 -04:00
) ) ;
2020-10-28 06:51:40 -04:00
2021-03-17 15:17:35 -04:00
Section . AddMenuEntry ( " AddSelectedActorsToSelectedDataLayers " , LOCTEXT ( " AddSelectedActorsToSelectedDataLayers " , " Add Selected Actors to Selected Data Layers " ) , FText ( ) , FSlateIcon ( ) ,
2020-10-28 06:51:40 -04:00
FUIAction (
FExecuteAction : : CreateLambda ( [ = ] ( ) {
check ( ! SelectedDataLayers . IsEmpty ( ) ) ;
{
2021-03-17 15:17:35 -04:00
const FScopedTransaction Transaction ( LOCTEXT ( " AddSelectedActorsToSelectedDataLayers " , " Add Selected Actors to Selected Data Layers " ) ) ;
2020-10-28 06:51:40 -04:00
DataLayerEditorSubsystem - > AddSelectedActorsToDataLayers ( SelectedDataLayers ) ;
} } ) ,
FCanExecuteAction : : CreateLambda ( [ = ] { return ! SelectedDataLayers . IsEmpty ( ) & & GEditor - > GetSelectedActorCount ( ) > 0 ; } )
2020-12-03 12:41:42 -04:00
) ) ;
2020-10-28 06:51:40 -04:00
Section . AddSeparator ( " SectionsSeparator " ) ;
2021-03-17 15:17:35 -04:00
Section . AddMenuEntry ( " RemoveSelectedActorsFromSelectedDataLayers " , LOCTEXT ( " RemoveSelectedActorsFromSelectedDataLayers " , " Remove Selected Actors from Selected Data Layers " ) , FText ( ) , FSlateIcon ( ) ,
2020-10-28 06:51:40 -04:00
FUIAction (
FExecuteAction : : CreateLambda ( [ = ] ( ) {
check ( ! SelectedDataLayers . IsEmpty ( ) ) ;
{
2021-03-17 15:17:35 -04:00
const FScopedTransaction Transaction ( LOCTEXT ( " RemoveSelectedActorsFromSelectedDataLayers " , " Remove Selected Actors from Selected Data Layers " ) ) ;
2020-10-28 06:51:40 -04:00
DataLayerEditorSubsystem - > RemoveSelectedActorsFromDataLayers ( SelectedDataLayers ) ;
} } ) ,
FCanExecuteAction : : CreateLambda ( [ = ] { return ! SelectedDataLayers . IsEmpty ( ) & & GEditor - > GetSelectedActorCount ( ) > 0 ; } )
2020-12-03 12:41:42 -04:00
) ) ;
2020-10-28 06:51:40 -04:00
2021-03-17 15:17:35 -04:00
Section . AddMenuEntry ( " DeleteSelectedDataLayers " , LOCTEXT ( " DeleteSelectedDataLayers " , " Delete Selected Data Layers " ) , FText ( ) , FSlateIcon ( ) ,
2020-10-28 06:51:40 -04:00
FUIAction (
FExecuteAction : : CreateLambda ( [ = ] ( ) {
check ( ! SelectedDataLayers . IsEmpty ( ) ) ;
{
2021-03-17 15:17:35 -04:00
const FScopedTransaction Transaction ( LOCTEXT ( " DeleteSelectedDataLayers " , " Delete Selected Data Layers " ) ) ;
2020-10-28 06:51:40 -04:00
DataLayerEditorSubsystem - > DeleteDataLayers ( SelectedDataLayers ) ;
} } ) ,
2021-02-09 15:01:37 -04:00
FCanExecuteAction : : CreateLambda ( [ = ] {
for ( UDataLayer * SelectedDataLayer : SelectedDataLayers )
{
if ( SelectedDataLayer - > IsLocked ( ) )
{
return false ;
}
}
return ! SelectedDataLayers . IsEmpty ( ) ;
} )
2020-12-03 12:41:42 -04:00
) ) ;
2020-10-28 06:51:40 -04:00
2021-03-17 15:17:35 -04:00
Section . AddMenuEntry ( " RenameSelectedDataLayer " , LOCTEXT ( " RenameSelectedDataLayer " , " Rename Selected Data Layer " ) , FText ( ) , FSlateIcon ( ) ,
2020-10-28 06:51:40 -04:00
FUIAction (
FExecuteAction : : CreateLambda ( [ = ] ( ) {
if ( SelectedDataLayers . Num ( ) = = 1 )
{
FSceneOutlinerTreeItemPtr ItemToRename = SceneOutliner - > GetTreeItem ( SelectedDataLayers [ 0 ] ) ;
if ( ItemToRename . IsValid ( ) & & CanRenameItem ( * ItemToRename ) & & ItemToRename - > CanInteract ( ) )
{
SceneOutliner - > SetPendingRenameItem ( ItemToRename ) ;
SceneOutliner - > ScrollItemIntoView ( ItemToRename ) ;
}
} } ) ,
2021-02-09 15:01:37 -04:00
FCanExecuteAction : : CreateLambda ( [ = ] { return ( SelectedDataLayers . Num ( ) = = 1 ) & & ! SelectedDataLayers [ 0 ] - > IsLocked ( ) ; } )
2020-12-03 12:41:42 -04:00
) ) ;
2020-10-28 06:51:40 -04:00
Section . AddSeparator ( " SectionsSeparator " ) ;
}
{
FToolMenuSection & Section = InMenu - > AddSection ( " DataLayerSelection " , LOCTEXT ( " DataLayerSelection " , " Selection " ) ) ;
2021-03-17 15:17:35 -04:00
Section . AddMenuEntry ( " SelectActorsInDataLayers " , LOCTEXT ( " SelectActorsInDataLayers " , " Select Actors in Data Layers " ) , FText ( ) , FSlateIcon ( ) ,
2020-10-28 06:51:40 -04:00
FUIAction (
FExecuteAction : : CreateLambda ( [ = ] ( ) {
check ( ! SelectedDataLayers . IsEmpty ( ) ) ;
{
2021-03-17 15:17:35 -04:00
const FScopedTransaction Transaction ( LOCTEXT ( " SelectActorsInDataLayers " , " Select Actors in Data Layers " ) ) ;
2020-10-28 06:51:40 -04:00
GEditor - > SelectNone ( /*bNoteSelectionChange*/ false , /*bDeselectBSPSurfs*/ true ) ;
DataLayerEditorSubsystem - > SelectActorsInDataLayers ( SelectedDataLayers , /*bSelect*/ true , /*bNotify*/ true , /*bSelectEvenIfHidden*/ true ) ;
} } ) ,
FCanExecuteAction : : CreateLambda ( [ = ] { return ! SelectedDataLayers . IsEmpty ( ) ; } )
2020-12-03 12:41:42 -04:00
) ) ;
2020-10-28 06:51:40 -04:00
2021-03-17 15:17:35 -04:00
Section . AddMenuEntry ( " AppendActorsToSelection " , LOCTEXT ( " AppendActorsToSelection " , " Append Actors in Data Layer to Selection " ) , FText ( ) , FSlateIcon ( ) ,
2020-10-28 06:51:40 -04:00
FUIAction (
FExecuteAction : : CreateLambda ( [ = ] ( ) {
check ( ! SelectedDataLayers . IsEmpty ( ) ) ;
{
2021-03-17 15:17:35 -04:00
const FScopedTransaction Transaction ( LOCTEXT ( " AppendActorsToSelection " , " Append Actors in Data Layer to Selection " ) ) ;
2020-10-28 06:51:40 -04:00
DataLayerEditorSubsystem - > SelectActorsInDataLayers ( SelectedDataLayers , /*bSelect*/ true , /*bNotify*/ true , /*bSelectEvenIfHidden*/ true ) ;
} } ) ,
FCanExecuteAction : : CreateLambda ( [ = ] { return ! SelectedDataLayers . IsEmpty ( ) ; } )
2020-12-03 12:41:42 -04:00
) ) ;
2020-10-28 06:51:40 -04:00
2021-03-17 15:17:35 -04:00
Section . AddMenuEntry ( " DeselectActors " , LOCTEXT ( " DeselectActors " , " Deselect Actors in Data Layer " ) , FText ( ) , FSlateIcon ( ) ,
2020-10-28 06:51:40 -04:00
FUIAction (
FExecuteAction : : CreateLambda ( [ = ] ( ) {
check ( ! SelectedDataLayers . IsEmpty ( ) ) ;
{
2021-03-17 15:17:35 -04:00
const FScopedTransaction Transaction ( LOCTEXT ( " DeselectActors " , " Deselect Actors in Data Layer " ) ) ;
2020-10-28 06:51:40 -04:00
DataLayerEditorSubsystem - > SelectActorsInDataLayers ( SelectedDataLayers , /*bSelect*/ false , /*bNotifySelectActors*/ true ) ;
} } ) ,
FCanExecuteAction : : CreateLambda ( [ = ] { return ! SelectedDataLayers . IsEmpty ( ) ; } )
2020-12-03 12:41:42 -04:00
) ) ;
2020-10-28 06:51:40 -04:00
}
{
FToolMenuSection & Section = InMenu - > AddSection ( " DataLayerVisibility " , LOCTEXT ( " DataLayerVisibility " , " Visibility " ) ) ;
2021-03-17 15:17:35 -04:00
Section . AddMenuEntry ( " MakeAllDataLayersVisible " , LOCTEXT ( " MakeAllDataLayersVisible " , " Make All Data Layers Visible " ) , FText ( ) , FSlateIcon ( ) ,
2020-10-28 06:51:40 -04:00
FUIAction (
FExecuteAction : : CreateLambda ( [ = ] ( ) {
check ( ! AllDataLayers . IsEmpty ( ) ) ;
{
2021-03-17 15:17:35 -04:00
const FScopedTransaction Transaction ( LOCTEXT ( " MakeAllDataLayersVisible " , " Make All Data Layers Visible " ) ) ;
2020-10-28 06:51:40 -04:00
DataLayerEditorSubsystem - > MakeAllDataLayersVisible ( ) ;
} } ) ,
FCanExecuteAction : : CreateLambda ( [ = ] { return ! AllDataLayers . IsEmpty ( ) ; } )
2020-12-03 12:41:42 -04:00
) ) ;
2020-10-28 06:51:40 -04:00
}
} ) ) ;
}
if ( ! ToolMenus - > IsMenuRegistered ( DefaultContextMenuName ) )
{
ToolMenus - > RegisterMenu ( DefaultContextMenuName , DefaultContextBaseMenuName ) ;
}
}
TSharedPtr < SWidget > FDataLayerMode : : CreateContextMenu ( )
{
RegisterContextMenu ( ) ;
FSceneOutlinerItemSelection ItemSelection ( SceneOutliner - > GetSelection ( ) ) ;
USceneOutlinerMenuContext * ContextObject = NewObject < USceneOutlinerMenuContext > ( ) ;
ContextObject - > SceneOutliner = StaticCastSharedRef < SSceneOutliner > ( SceneOutliner - > AsShared ( ) ) ;
ContextObject - > bShowParentTree = SceneOutliner - > GetSharedData ( ) . bShowParentTree ;
ContextObject - > NumSelectedItems = ItemSelection . Num ( ) ;
FToolMenuContext Context ( ContextObject ) ;
FName MenuName = DefaultContextMenuName ;
SceneOutliner - > GetSharedData ( ) . ModifyContextMenu . ExecuteIfBound ( MenuName , Context ) ;
// Build up the menu for a selection
UToolMenus * ToolMenus = UToolMenus : : Get ( ) ;
UToolMenu * Menu = ToolMenus - > GenerateMenu ( MenuName , Context ) ;
for ( const FToolMenuSection & Section : Menu - > Sections )
{
if ( Section . Blocks . Num ( ) > 0 )
{
return ToolMenus - > GenerateWidget ( Menu ) ;
}
}
return nullptr ;
}
TUniquePtr < ISceneOutlinerHierarchy > FDataLayerMode : : CreateHierarchy ( )
{
TUniquePtr < FDataLayerHierarchy > ActorHierarchy = FDataLayerHierarchy : : Create ( this , RepresentingWorld ) ;
return ActorHierarchy ;
}
2020-11-03 17:16:48 -04:00
void FDataLayerMode : : OnItemSelectionChanged ( FSceneOutlinerTreeItemPtr TreeItem , ESelectInfo : : Type SelectionType , const FSceneOutlinerItemSelection & Selection )
{
2020-11-03 18:28:22 -04:00
SelectedDataLayersSet . Empty ( ) ;
2020-11-03 17:16:48 -04:00
SelectedDataLayerActors . Empty ( ) ;
2020-11-03 18:28:22 -04:00
Selection . ForEachItem < FDataLayerTreeItem > ( [ this ] ( const FDataLayerTreeItem & Item ) { SelectedDataLayersSet . Add ( Item . GetDataLayer ( ) ) ; } ) ;
2020-11-03 17:16:48 -04:00
Selection . ForEachItem < FDataLayerActorTreeItem > ( [ this ] ( const FDataLayerActorTreeItem & Item ) { SelectedDataLayerActors . Add ( FSelectedDataLayerActor ( Item . GetDataLayer ( ) , Item . GetActor ( ) ) ) ; } ) ;
2021-01-27 13:03:11 -04:00
if ( DataLayerBrowser )
{
DataLayerBrowser - > OnSelectionChanged ( SelectedDataLayersSet ) ;
}
2020-11-03 17:16:48 -04:00
}
2020-10-28 06:51:40 -04:00
void FDataLayerMode : : Rebuild ( )
{
ChooseRepresentingWorld ( ) ;
2020-11-03 17:16:48 -04:00
2020-10-28 06:51:40 -04:00
Hierarchy = CreateHierarchy ( ) ;
}
void FDataLayerMode : : ChooseRepresentingWorld ( )
{
// Select a world to represent
RepresentingWorld = nullptr ;
// If a specified world was provided, represent it
if ( SpecifiedWorldToDisplay . IsValid ( ) )
{
RepresentingWorld = SpecifiedWorldToDisplay . Get ( ) ;
}
// check if the user-chosen world is valid and in the editor contexts
if ( ! RepresentingWorld . IsValid ( ) & & UserChosenWorld . IsValid ( ) )
{
for ( const FWorldContext & Context : GEngine - > GetWorldContexts ( ) )
{
if ( UserChosenWorld . Get ( ) = = Context . World ( ) )
{
RepresentingWorld = UserChosenWorld . Get ( ) ;
break ;
}
}
}
// If the user did not manually select a world, try to pick the most suitable world context
if ( ! RepresentingWorld . IsValid ( ) )
{
// ideally we want a PIE world that is standalone or the first client
for ( const FWorldContext & Context : GEngine - > GetWorldContexts ( ) )
{
UWorld * World = Context . World ( ) ;
if ( World & & Context . WorldType = = EWorldType : : PIE )
{
if ( World - > GetNetMode ( ) = = NM_Standalone )
{
RepresentingWorld = World ;
break ;
}
else if ( World - > GetNetMode ( ) = = NM_Client & & Context . PIEInstance = = 2 ) / / Slightly dangerous : assumes server is always PIEInstance = 1 ;
{
RepresentingWorld = World ;
break ;
}
}
}
}
if ( RepresentingWorld = = nullptr )
{
// still not world so fallback to old logic where we just prefer PIE over Editor
for ( const FWorldContext & Context : GEngine - > GetWorldContexts ( ) )
{
if ( Context . WorldType = = EWorldType : : PIE )
{
RepresentingWorld = Context . World ( ) ;
break ;
}
else if ( Context . WorldType = = EWorldType : : Editor )
{
RepresentingWorld = Context . World ( ) ;
}
}
}
}
2021-04-19 10:09:54 -04:00
# undef LOCTEXT_NAMESPACE