2020-08-25 06:31:46 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
# include "LevelInstanceEditorModule.h"
# include "LevelInstanceActorDetails.h"
2021-01-18 12:50:54 -04:00
# include "LevelInstancePivotDetails.h"
2023-06-14 06:25:37 -04:00
# include "PackedLevelActorUtils.h"
2023-03-08 12:02:09 -05:00
# include "LevelInstanceFilterPropertyTypeCustomization.h"
2020-08-25 06:31:46 -04:00
# include "LevelInstance/LevelInstanceSubsystem.h"
2022-03-29 09:19:22 -04:00
# include "LevelInstance/LevelInstanceInterface.h"
2020-08-25 06:31:46 -04:00
# include "LevelInstance/LevelInstanceActor.h"
2021-12-09 08:09:34 -05:00
# include "PackedLevelActor/PackedLevelActor.h"
2023-06-22 13:32:10 -04:00
# include "PackedLevelActor/PackedLevelActorBuilder.h"
2020-08-25 06:31:46 -04:00
# include "LevelInstanceEditorSettings.h"
# include "ToolMenus.h"
# include "Editor.h"
2021-11-29 14:47:15 -05:00
# include "EditorModeManager.h"
# include "EditorModeRegistry.h"
2022-08-31 08:51:11 -04:00
# include "FileHelpers.h"
2021-11-29 14:47:15 -05:00
# include "LevelInstanceEditorMode.h"
# include "LevelInstanceEditorModeCommands.h"
2020-08-25 06:31:46 -04:00
# include "LevelEditorMenuContext.h"
# include "ContentBrowserMenuContexts.h"
# include "ContentBrowserModule.h"
# include "IContentBrowserSingleton.h"
# include "LevelEditor.h"
# include "Engine/Selection.h"
# include "PropertyEditorModule.h"
# include "EditorLevelUtils.h"
# include "Modules/ModuleManager.h"
# include "Misc/MessageDialog.h"
# include "NewLevelDialogModule.h"
# include "Interfaces/IMainFrameModule.h"
# include "Editor/EditorEngine.h"
# include "AssetToolsModule.h"
# include "IAssetTools.h"
# include "Factories/BlueprintFactory.h"
# include "ClassViewerModule.h"
# include "ClassViewerFilter.h"
# include "Kismet2/BlueprintEditorUtils.h"
# include "Misc/ScopeExit.h"
# include "Widgets/Input/SNumericEntryBox.h"
2020-08-31 23:09:34 -04:00
# include "Widgets/Input/SButton.h"
2021-01-18 12:50:54 -04:00
# include "Widgets/SWindow.h"
# include "SNewLevelInstanceDialog.h"
2020-11-16 08:50:22 -04:00
# include "MessageLogModule.h"
2022-01-07 11:45:52 -05:00
# include "Settings/EditorExperimentalSettings.h"
2022-08-31 08:51:11 -04:00
# include "WorldPartition/WorldPartitionConverter.h"
2023-03-08 12:02:09 -05:00
# include "WorldPartition/WorldPartitionActorLoaderInterface.h"
2020-08-25 06:31:46 -04:00
IMPLEMENT_MODULE ( FLevelInstanceEditorModule , LevelInstanceEditor ) ;
# define LOCTEXT_NAMESPACE "LevelInstanceEditor"
2022-09-14 07:32:55 -04:00
DEFINE_LOG_CATEGORY_STATIC ( LogLevelInstanceEditor , Log , All ) ;
2020-08-25 06:31:46 -04:00
namespace LevelInstanceMenuUtils
{
2022-03-29 09:19:22 -04:00
bool IsExperimentalSettingEnabled ( ILevelInstanceInterface * LevelInstance )
2022-01-07 11:45:52 -05:00
{
2022-03-29 09:19:22 -04:00
if ( APackedLevelActor * Actor = Cast < APackedLevelActor > ( LevelInstance ) )
2022-01-07 11:45:52 -05:00
{
2022-03-29 09:19:22 -04:00
if ( ! GetDefault < UEditorExperimentalSettings > ( ) - > bPackedLevelActor )
{
return false ;
}
2022-01-07 11:45:52 -05:00
}
return GetDefault < UEditorExperimentalSettings > ( ) - > bLevelInstance ;
}
2021-12-09 08:09:34 -05:00
FToolMenuSection & CreateLevelSection ( UToolMenu * Menu )
2020-08-25 06:31:46 -04:00
{
2021-12-09 08:09:34 -05:00
const FName LevelSectionName = TEXT ( " Level " ) ;
FToolMenuSection * SectionPtr = Menu - > FindSection ( LevelSectionName ) ;
2021-03-19 18:18:42 -04:00
if ( ! SectionPtr )
{
2021-12-09 08:09:34 -05:00
SectionPtr = & ( Menu - > AddSection ( LevelSectionName , LOCTEXT ( " LevelSectionLabel " , " Level " ) ) ) ;
2021-03-19 18:18:42 -04:00
}
FToolMenuSection & Section = * SectionPtr ;
2020-08-25 06:31:46 -04:00
return Section ;
}
2022-03-29 09:19:22 -04:00
void CreateEditMenuEntry ( FToolMenuSection & Section , ILevelInstanceInterface * LevelInstance , AActor * ContextActor , bool bSingleEntry )
2021-12-01 12:13:41 -05:00
{
FToolUIAction LevelInstanceEditAction ;
FText EntryDesc ;
2022-03-29 09:19:22 -04:00
AActor * LevelInstanceActor = CastChecked < AActor > ( LevelInstance ) ;
const bool bCanEdit = LevelInstance - > CanEnterEdit ( & EntryDesc ) ;
2021-12-01 12:13:41 -05:00
LevelInstanceEditAction . ExecuteAction . BindLambda ( [ LevelInstance , ContextActor ] ( const FToolMenuContext & )
{
2022-03-29 09:19:22 -04:00
LevelInstance - > EnterEdit ( ContextActor ) ;
2021-12-01 12:13:41 -05:00
} ) ;
LevelInstanceEditAction . CanExecuteAction . BindLambda ( [ bCanEdit ] ( const FToolMenuContext & )
{
return bCanEdit ;
} ) ;
FText EntryLabel = bSingleEntry ? LOCTEXT ( " EditLevelInstances " , " Edit " ) : FText : : FromString ( LevelInstance - > GetWorldAsset ( ) . GetAssetName ( ) ) ;
if ( bCanEdit )
{
2022-03-29 09:19:22 -04:00
EntryDesc = FText : : Format ( LOCTEXT ( " LevelInstanceName " , " {0}:{1} " ) , FText : : FromString ( LevelInstanceActor - > GetActorLabel ( ) ) , FText : : FromString ( LevelInstance - > GetWorldAssetPackage ( ) ) ) ;
2021-12-01 12:13:41 -05:00
}
Section . AddMenuEntry ( NAME_None , EntryLabel , EntryDesc , FSlateIcon ( ) , LevelInstanceEditAction ) ;
}
2022-03-29 09:19:22 -04:00
void CreateEditSubMenu ( UToolMenu * Menu , TArray < ILevelInstanceInterface * > LevelInstanceHierarchy , AActor * ContextActor )
2020-08-25 06:31:46 -04:00
{
FToolMenuSection & Section = Menu - > AddSection ( NAME_None , LOCTEXT ( " LevelInstanceContextEditSection " , " Context " ) ) ;
2022-03-29 09:19:22 -04:00
for ( ILevelInstanceInterface * LevelInstance : LevelInstanceHierarchy )
2020-08-25 06:31:46 -04:00
{
2021-12-01 12:13:41 -05:00
CreateEditMenuEntry ( Section , LevelInstance , ContextActor , false ) ;
2020-08-25 06:31:46 -04:00
}
}
2022-03-29 09:19:22 -04:00
void MoveSelectionToLevelInstance ( ILevelInstanceInterface * DestinationLevelInstance )
2020-08-25 06:31:46 -04:00
{
2022-03-29 09:19:22 -04:00
TArray < AActor * > ActorsToMove ;
ActorsToMove . Reserve ( GEditor - > GetSelectedActorCount ( ) ) ;
for ( FSelectionIterator It ( GEditor - > GetSelectedActorIterator ( ) ) ; It ; + + It )
2020-08-25 06:31:46 -04:00
{
2022-03-29 09:19:22 -04:00
if ( AActor * Actor = Cast < AActor > ( * It ) )
2020-08-25 06:31:46 -04:00
{
2022-03-29 09:19:22 -04:00
ActorsToMove . Add ( Actor ) ;
2020-08-25 06:31:46 -04:00
}
}
2022-03-29 09:19:22 -04:00
DestinationLevelInstance - > MoveActorsTo ( ActorsToMove ) ;
2020-08-25 06:31:46 -04:00
}
2021-11-25 11:13:02 -05:00
2020-08-25 06:31:46 -04:00
void CreateEditMenu ( UToolMenu * Menu , AActor * ContextActor )
{
if ( ULevelInstanceSubsystem * LevelInstanceSubsystem = ContextActor - > GetWorld ( ) - > GetSubsystem < ULevelInstanceSubsystem > ( ) )
{
2022-03-29 09:19:22 -04:00
TArray < ILevelInstanceInterface * > LevelInstanceHierarchy ;
LevelInstanceSubsystem - > ForEachLevelInstanceAncestorsAndSelf ( ContextActor , [ & LevelInstanceHierarchy ] ( ILevelInstanceInterface * AncestorLevelInstance )
2020-08-25 06:31:46 -04:00
{
2022-01-07 11:45:52 -05:00
if ( IsExperimentalSettingEnabled ( AncestorLevelInstance ) )
{
LevelInstanceHierarchy . Add ( AncestorLevelInstance ) ;
}
2020-08-25 06:31:46 -04:00
return true ;
} ) ;
2021-12-01 12:13:41 -05:00
// Don't create sub menu if only one Level Instance is available to edit
if ( LevelInstanceHierarchy . Num ( ) = = 1 )
{
2021-12-09 08:09:34 -05:00
FToolMenuSection & Section = CreateLevelSection ( Menu ) ;
2021-12-01 12:13:41 -05:00
CreateEditMenuEntry ( Section , LevelInstanceHierarchy [ 0 ] , ContextActor , true ) ;
}
else if ( LevelInstanceHierarchy . Num ( ) > 1 )
2020-08-25 06:31:46 -04:00
{
2021-12-09 08:09:34 -05:00
FToolMenuSection & Section = CreateLevelSection ( Menu ) ;
2020-08-25 06:31:46 -04:00
Section . AddSubMenu (
" EditLevelInstances " ,
LOCTEXT ( " EditLevelInstances " , " Edit " ) ,
TAttribute < FText > ( ) ,
FNewToolMenuDelegate : : CreateStatic ( & CreateEditSubMenu , MoveTemp ( LevelInstanceHierarchy ) , ContextActor )
) ;
}
}
}
2022-06-08 12:14:52 -04:00
2022-01-04 07:28:59 -05:00
void CreateCommitDiscardMenu ( UToolMenu * Menu , AActor * ContextActor )
2020-08-25 06:31:46 -04:00
{
2022-03-29 09:19:22 -04:00
ILevelInstanceInterface * LevelInstanceEdit = nullptr ;
2020-08-25 06:31:46 -04:00
if ( ContextActor )
{
if ( ULevelInstanceSubsystem * LevelInstanceSubsystem = ContextActor - > GetWorld ( ) - > GetSubsystem < ULevelInstanceSubsystem > ( ) )
{
2021-11-25 11:13:02 -05:00
LevelInstanceEdit = LevelInstanceSubsystem - > GetEditingLevelInstance ( ) ;
2020-08-25 06:31:46 -04:00
}
}
2021-11-25 11:13:02 -05:00
if ( ! LevelInstanceEdit )
2020-08-25 06:31:46 -04:00
{
2021-11-25 11:13:02 -05:00
if ( ULevelInstanceSubsystem * LevelInstanceSubsystem = GEditor - > GetEditorWorldContext ( ) . World ( ) - > GetSubsystem < ULevelInstanceSubsystem > ( ) )
2020-08-25 06:31:46 -04:00
{
2021-11-25 11:13:02 -05:00
LevelInstanceEdit = LevelInstanceSubsystem - > GetEditingLevelInstance ( ) ;
}
2020-08-25 06:31:46 -04:00
}
2021-11-25 11:13:02 -05:00
if ( LevelInstanceEdit )
2020-08-25 06:31:46 -04:00
{
2022-01-04 07:28:59 -05:00
FToolMenuSection & Section = CreateLevelSection ( Menu ) ;
2021-11-25 11:13:02 -05:00
2022-01-04 07:28:59 -05:00
FText CommitTooltip ;
2022-03-29 09:19:22 -04:00
const bool bCanCommit = LevelInstanceEdit - > CanExitEdit ( /*bDiscardEdits=*/ false , & CommitTooltip ) ;
2021-11-25 11:13:02 -05:00
2022-01-04 07:28:59 -05:00
FToolUIAction CommitAction ;
2022-03-29 09:19:22 -04:00
CommitAction . ExecuteAction . BindLambda ( [ LevelInstanceEdit ] ( const FToolMenuContext & ) { LevelInstanceEdit - > ExitEdit ( /*bDiscardEdits=*/ false ) ; } ) ;
2022-01-04 07:28:59 -05:00
CommitAction . CanExecuteAction . BindLambda ( [ bCanCommit ] ( const FToolMenuContext & ) { return bCanCommit ; } ) ;
Section . AddMenuEntry ( NAME_None , LOCTEXT ( " LevelInstanceCommitLabel " , " Commit " ) , CommitTooltip , FSlateIcon ( ) , CommitAction ) ;
2021-11-25 11:13:02 -05:00
2022-01-04 07:28:59 -05:00
FText DiscardTooltip ;
2022-03-29 09:19:22 -04:00
const bool bCanDiscard = LevelInstanceEdit - > CanExitEdit ( /*bDiscardEdits=*/ true , & DiscardTooltip ) ;
2022-01-04 07:28:59 -05:00
FToolUIAction DiscardAction ;
2022-03-29 09:19:22 -04:00
DiscardAction . ExecuteAction . BindLambda ( [ LevelInstanceEdit ] ( const FToolMenuContext & ) { LevelInstanceEdit - > ExitEdit ( /*bDiscardEdits=*/ true ) ; } ) ;
2022-01-04 07:28:59 -05:00
DiscardAction . CanExecuteAction . BindLambda ( [ bCanDiscard ] ( const FToolMenuContext & ) { return bCanDiscard ; } ) ;
Section . AddMenuEntry ( NAME_None , LOCTEXT ( " LevelInstanceDiscardLabel " , " Discard " ) , DiscardTooltip , FSlateIcon ( ) , DiscardAction ) ;
2020-08-25 06:31:46 -04:00
}
}
void CreateSetCurrentMenu ( UToolMenu * Menu , AActor * ContextActor )
{
2022-03-29 09:19:22 -04:00
ILevelInstanceInterface * LevelInstanceEdit = nullptr ;
2021-11-25 11:13:02 -05:00
if ( ULevelInstanceSubsystem * LevelInstanceSubsystem = ContextActor - > GetWorld ( ) - > GetSubsystem < ULevelInstanceSubsystem > ( ) )
2020-08-25 06:31:46 -04:00
{
2022-01-26 15:37:41 -05:00
LevelInstanceEdit = LevelInstanceSubsystem - > GetEditingLevelInstance ( ) ;
2020-08-25 06:31:46 -04:00
2021-11-25 11:13:02 -05:00
if ( LevelInstanceEdit )
{
FToolUIAction LevelInstanceSetCurrentAction ;
LevelInstanceSetCurrentAction . ExecuteAction . BindLambda ( [ LevelInstanceEdit ] ( const FToolMenuContext & )
2022-03-29 09:19:22 -04:00
{
LevelInstanceEdit - > SetCurrent ( ) ;
} ) ;
2021-11-25 11:13:02 -05:00
2021-12-09 08:09:34 -05:00
FToolMenuSection & Section = CreateLevelSection ( Menu ) ;
2022-05-04 08:58:05 -04:00
Section . AddMenuEntry ( TEXT ( " LevelInstanceSetCurrent " ) , LOCTEXT ( " LevelInstanceSetCurrent " , " Set Current Level " ) , TAttribute < FText > ( ) , FSlateIcon ( ) , LevelInstanceSetCurrentAction ) ;
2021-11-25 11:13:02 -05:00
}
2020-08-25 06:31:46 -04:00
}
}
void CreateMoveSelectionToMenu ( UToolMenu * Menu )
{
if ( GEditor - > GetSelectedActorCount ( ) > 0 )
{
2022-03-29 09:19:22 -04:00
ILevelInstanceInterface * LevelInstanceEdit = nullptr ;
2021-11-25 11:13:02 -05:00
ULevelInstanceSubsystem * LevelInstanceSubsystem = GEditor - > GetEditorWorldContext ( ) . World ( ) - > GetSubsystem < ULevelInstanceSubsystem > ( ) ;
if ( LevelInstanceSubsystem )
2020-08-25 06:31:46 -04:00
{
2021-11-25 11:13:02 -05:00
LevelInstanceEdit = LevelInstanceSubsystem - > GetEditingLevelInstance ( ) ;
2020-08-25 06:31:46 -04:00
}
2021-11-25 11:13:02 -05:00
if ( LevelInstanceEdit )
2020-08-25 06:31:46 -04:00
{
2021-11-25 11:13:02 -05:00
FToolUIAction LevelInstanceMoveSelectionAction ;
LevelInstanceMoveSelectionAction . CanExecuteAction . BindLambda ( [ LevelInstanceEdit , LevelInstanceSubsystem ] ( const FToolMenuContext & MenuContext )
{
for ( FSelectionIterator It ( GEditor - > GetSelectedActorIterator ( ) ) ; It ; + + It )
{
if ( AActor * Actor = Cast < AActor > ( * It ) )
{
if ( Actor - > GetLevel ( ) = = LevelInstanceSubsystem - > GetLevelInstanceLevel ( LevelInstanceEdit ) )
{
return false ;
}
}
}
return GEditor - > GetSelectedActorCount ( ) > 0 ;
} ) ;
LevelInstanceMoveSelectionAction . ExecuteAction . BindLambda ( [ LevelInstanceEdit ] ( const FToolMenuContext & )
{
MoveSelectionToLevelInstance ( LevelInstanceEdit ) ;
} ) ;
2021-12-09 08:09:34 -05:00
FToolMenuSection & Section = CreateLevelSection ( Menu ) ;
2022-05-04 08:58:05 -04:00
Section . AddMenuEntry ( TEXT ( " LevelInstanceMoveSelectionTo " ) , LOCTEXT ( " LevelInstanceMoveSelectionTo " , " Move Selection to " ) , TAttribute < FText > ( ) , FSlateIcon ( ) , LevelInstanceMoveSelectionAction ) ;
2021-11-25 11:13:02 -05:00
2020-08-25 06:31:46 -04:00
}
}
}
2023-05-19 13:51:16 -04:00
UClass * GetDefaultLevelInstanceClass ( ELevelInstanceCreationType CreationType )
{
if ( CreationType = = ELevelInstanceCreationType : : PackedLevelActor )
{
return APackedLevelActor : : StaticClass ( ) ;
}
ULevelInstanceEditorSettings * LevelInstanceEditorSettings = GetMutableDefault < ULevelInstanceEditorSettings > ( ) ;
if ( ! LevelInstanceEditorSettings - > LevelInstanceClassName . IsEmpty ( ) )
{
UClass * LevelInstanceClass = LoadClass < AActor > ( nullptr , * LevelInstanceEditorSettings - > LevelInstanceClassName , nullptr , LOAD_NoWarn ) ;
if ( LevelInstanceClass & & LevelInstanceClass - > ImplementsInterface ( ULevelInstanceInterface : : StaticClass ( ) ) )
{
return LevelInstanceClass ;
}
}
return ALevelInstance : : StaticClass ( ) ;
}
2021-12-09 08:09:34 -05:00
void CreateLevelInstanceFromSelection ( ULevelInstanceSubsystem * LevelInstanceSubsystem , ELevelInstanceCreationType CreationType )
2020-08-25 06:31:46 -04:00
{
TArray < AActor * > ActorsToMove ;
ActorsToMove . Reserve ( GEditor - > GetSelectedActorCount ( ) ) ;
for ( FSelectionIterator It ( GEditor - > GetSelectedActorIterator ( ) ) ; It ; + + It )
{
if ( AActor * Actor = Cast < AActor > ( * It ) )
{
ActorsToMove . Add ( Actor ) ;
}
}
IMainFrameModule & MainFrameModule = FModuleManager : : GetModuleChecked < IMainFrameModule > ( " MainFrame " ) ;
2021-01-18 12:50:54 -04:00
TSharedPtr < SWindow > NewLevelInstanceWindow =
SNew ( SWindow )
2021-12-09 08:09:34 -05:00
. Title ( FText : : Format ( LOCTEXT ( " NewLevelInstanceWindowTitle " , " New {0} " ) , StaticEnum < ELevelInstanceCreationType > ( ) - > GetDisplayNameTextByValue ( ( int64 ) CreationType ) ) )
2021-01-18 12:50:54 -04:00
. SupportsMinimize ( false )
. SupportsMaximize ( false )
2021-12-09 08:09:34 -05:00
. SizingRule ( ESizingRule : : Autosized ) ;
2020-08-25 06:31:46 -04:00
2021-01-18 12:50:54 -04:00
TSharedRef < SNewLevelInstanceDialog > NewLevelInstanceDialog =
SNew ( SNewLevelInstanceDialog )
. ParentWindow ( NewLevelInstanceWindow )
. PivotActors ( ActorsToMove ) ;
2021-11-25 13:29:54 -05:00
const bool bForceExternalActors = LevelInstanceSubsystem - > GetWorld ( ) - > IsPartitionedWorld ( ) ;
FNewLevelInstanceParams & DialogParams = NewLevelInstanceDialog - > GetCreationParams ( ) ;
2021-12-09 08:09:34 -05:00
DialogParams . Type = CreationType ;
2022-06-13 18:38:57 -04:00
DialogParams . bAlwaysShowDialog = GetDefault < ULevelInstanceEditorPerProjectUserSettings > ( ) - > bAlwaysShowDialog ;
DialogParams . PivotType = GetDefault < ULevelInstanceEditorPerProjectUserSettings > ( ) - > PivotType ;
DialogParams . PivotActor = DialogParams . PivotType = = ELevelInstancePivotType : : Actor ? ActorsToMove [ 0 ] : nullptr ;
2021-12-09 08:09:34 -05:00
DialogParams . HideCreationType ( ) ;
2021-11-25 13:29:54 -05:00
DialogParams . SetForceExternalActors ( bForceExternalActors ) ;
2021-01-18 12:50:54 -04:00
NewLevelInstanceWindow - > SetContent ( NewLevelInstanceDialog ) ;
2022-06-13 18:38:57 -04:00
if ( GetDefault < ULevelInstanceEditorPerProjectUserSettings > ( ) - > bAlwaysShowDialog )
{
FSlateApplication : : Get ( ) . AddModalWindow ( NewLevelInstanceWindow . ToSharedRef ( ) , MainFrameModule . GetParentWindow ( ) ) ;
}
if ( ! GetDefault < ULevelInstanceEditorPerProjectUserSettings > ( ) - > bAlwaysShowDialog | | NewLevelInstanceDialog - > ClickedOk ( ) )
2020-11-16 08:50:22 -04:00
{
2021-01-20 12:26:28 -04:00
FNewLevelInstanceParams CreationParams ( NewLevelInstanceDialog - > GetCreationParams ( ) ) ;
2022-06-13 18:38:57 -04:00
ULevelInstanceEditorPerProjectUserSettings : : UpdateFrom ( CreationParams ) ;
2021-01-18 12:50:54 -04:00
FNewLevelDialogModule & NewLevelDialogModule = FModuleManager : : LoadModuleChecked < FNewLevelDialogModule > ( " NewLevelDialog " ) ;
FString TemplateMapPackage ;
2021-09-29 12:29:37 -04:00
bool bOutIsPartitionedWorld = false ;
const bool bShowPartitionedTemplates = false ;
2022-05-16 09:27:00 -04:00
ULevelInstanceEditorSettings * LevelInstanceEditorSettings = GetMutableDefault < ULevelInstanceEditorSettings > ( ) ;
if ( ! LevelInstanceEditorSettings - > TemplateMapInfos . Num ( ) | | NewLevelDialogModule . CreateAndShowTemplateDialog ( MainFrameModule . GetParentWindow ( ) , LOCTEXT ( " LevelInstanceTemplateDialog " , " Choose Level Instance Template... " ) , GetMutableDefault < ULevelInstanceEditorSettings > ( ) - > TemplateMapInfos , TemplateMapPackage , bShowPartitionedTemplates , bOutIsPartitionedWorld ) )
2020-11-16 08:50:22 -04:00
{
2021-01-18 12:50:54 -04:00
UPackage * TemplatePackage = ! TemplateMapPackage . IsEmpty ( ) ? LoadPackage ( nullptr , * TemplateMapPackage , LOAD_None ) : nullptr ;
2021-01-20 12:26:28 -04:00
CreationParams . TemplateWorld = TemplatePackage ? UWorld : : FindWorldInPackage ( TemplatePackage ) : nullptr ;
2023-05-19 13:51:16 -04:00
CreationParams . LevelInstanceClass = GetDefaultLevelInstanceClass ( CreationType ) ;
2023-06-12 07:30:42 -04:00
CreationParams . bEnableStreaming = LevelInstanceEditorSettings - > bEnableStreaming ;
2021-01-18 12:50:54 -04:00
2021-01-20 12:26:28 -04:00
if ( ! LevelInstanceSubsystem - > CreateLevelInstanceFrom ( ActorsToMove , CreationParams ) )
2020-11-16 08:50:22 -04:00
{
2023-04-15 19:49:32 -04:00
FMessageDialog : : Open ( EAppMsgType : : Ok , LOCTEXT ( " CreateFromSelectionFailMsg " , " Failed to create from selection. Check log for details. " ) , LOCTEXT ( " CreateFromSelectionFailTitle " , " Create from selection failed " ) ) ;
2021-01-18 12:50:54 -04:00
}
2020-11-16 08:50:22 -04:00
}
}
}
2021-12-09 08:09:34 -05:00
void CreateCreateMenu ( UToolMenu * ToolMenu )
2020-08-25 06:31:46 -04:00
{
if ( ULevelInstanceSubsystem * LevelInstanceSubsystem = GEditor - > GetEditorWorldContext ( ) . World ( ) - > GetSubsystem < ULevelInstanceSubsystem > ( ) )
{
2021-12-09 08:09:34 -05:00
if ( GEditor - > GetSelectedActorCount ( ) > 0 )
2021-01-18 12:50:54 -04:00
{
2021-12-09 08:09:34 -05:00
FToolMenuSection & Section = ToolMenu - > AddSection ( " ActorSelectionSectionName " , LOCTEXT ( " ActorSelectionSectionLabel " , " Actor Selection " ) ) ;
2021-01-18 12:50:54 -04:00
2022-01-07 11:45:52 -05:00
if ( GetDefault < UEditorExperimentalSettings > ( ) - > bLevelInstance )
{
Section . AddMenuEntry (
2022-05-04 08:58:05 -04:00
TEXT ( " CreateLevelInstance " ) ,
2022-01-07 11:45:52 -05:00
FText : : Format ( LOCTEXT ( " CreateFromSelectionLabel " , " Create {0}... " ) , StaticEnum < ELevelInstanceCreationType > ( ) - > GetDisplayNameTextByValue ( ( int64 ) ELevelInstanceCreationType : : LevelInstance ) ) ,
TAttribute < FText > ( ) ,
FSlateIcon ( FAppStyle : : GetAppStyleSetName ( ) , " ClassIcon.LevelInstance " ) ,
FExecuteAction : : CreateStatic ( & LevelInstanceMenuUtils : : CreateLevelInstanceFromSelection , LevelInstanceSubsystem , ELevelInstanceCreationType : : LevelInstance ) ) ;
}
2021-12-09 08:09:34 -05:00
2022-01-07 11:45:52 -05:00
if ( GetDefault < UEditorExperimentalSettings > ( ) - > bPackedLevelActor )
{
Section . AddMenuEntry (
2022-05-04 08:58:05 -04:00
TEXT ( " CreatePackedLevelBlueprint " ) ,
2022-01-07 11:45:52 -05:00
FText : : Format ( LOCTEXT ( " CreateFromSelectionLabel " , " Create {0}... " ) , StaticEnum < ELevelInstanceCreationType > ( ) - > GetDisplayNameTextByValue ( ( int64 ) ELevelInstanceCreationType : : PackedLevelActor ) ) ,
TAttribute < FText > ( ) ,
FSlateIcon ( FAppStyle : : GetAppStyleSetName ( ) , " ClassIcon.PackedLevelActor " ) ,
FExecuteAction : : CreateStatic ( & LevelInstanceMenuUtils : : CreateLevelInstanceFromSelection , LevelInstanceSubsystem , ELevelInstanceCreationType : : PackedLevelActor ) ) ;
}
2021-12-09 08:09:34 -05:00
}
2020-08-25 06:31:46 -04:00
}
}
2021-12-09 08:09:34 -05:00
2022-06-17 14:13:33 -04:00
void CreateBreakSubMenu ( UToolMenu * Menu , TArray < ILevelInstanceInterface * > BreakableLevelInstances )
2020-08-25 06:31:46 -04:00
{
static int32 BreakLevels = 1 ;
2022-06-17 14:13:33 -04:00
if ( ULevelInstanceSubsystem * LevelInstanceSubsystem = GEditor - > GetEditorWorldContext ( ) . World ( ) - > GetSubsystem < ULevelInstanceSubsystem > ( ) )
2020-08-25 06:31:46 -04:00
{
FToolMenuSection & Section = Menu - > AddSection ( NAME_None , LOCTEXT ( " LevelInstanceBreakSection " , " Break Level Instance " ) ) ;
TSharedRef < SWidget > MenuWidget =
SNew ( SVerticalBox )
+ SVerticalBox : : Slot ( )
[
SNew ( SHorizontalBox )
+ SHorizontalBox : : Slot ( )
[
SNew ( SNumericEntryBox < int32 > )
. MinValue ( 1 )
. Value_Lambda ( [ ] ( ) { return BreakLevels ; } )
. OnValueChanged_Lambda ( [ ] ( int32 InValue ) { BreakLevels = InValue ; } )
. LabelPadding ( 0 )
. Label ( )
[
SNumericEntryBox < int32 > : : BuildLabel ( LOCTEXT ( " BreakLevelsLabel " , " Levels " ) , FLinearColor : : White , SNumericEntryBox < int32 > : : BlueLabelBackgroundColor )
]
]
]
+ SVerticalBox : : Slot ( )
. VAlign ( VAlign_Center )
. HAlign ( HAlign_Center )
. Padding ( 0 , 5 , 0 , 0 )
[
SNew ( SButton )
. HAlign ( HAlign_Center )
2022-05-09 13:12:28 -04:00
. ContentPadding ( FAppStyle : : GetMargin ( " StandardDialog.ContentPadding " ) )
2022-06-17 14:13:33 -04:00
. OnClicked_Lambda ( [ BreakableLevelInstances , LevelInstanceSubsystem ] ( )
{
const FText LevelInstanceBreakWarning = FText : : Format ( LOCTEXT ( " BreakingLevelInstance " , " You are about to break {0} level instance(s). This action cannot be undone. Are you sure ? " ) , FText : : FromString ( FString : : FromInt ( BreakableLevelInstances . Num ( ) ) ) ) ;
if ( FMessageDialog : : Open ( EAppMsgType : : YesNo , LevelInstanceBreakWarning ) = = EAppReturnType : : Yes )
2020-09-17 23:57:13 -04:00
{
2022-06-17 14:13:33 -04:00
for ( ILevelInstanceInterface * LevelInstance : BreakableLevelInstances )
2020-09-17 23:57:13 -04:00
{
2022-06-17 14:13:33 -04:00
LevelInstanceSubsystem - > BreakLevelInstance ( LevelInstance , BreakLevels ) ;
2020-09-17 23:57:13 -04:00
}
2022-06-17 14:13:33 -04:00
}
return FReply : : Handled ( ) ;
} )
. Text ( LOCTEXT ( " BreakLevelInstances_BreakLevelInstanceButton " , " Break Level Instance(s) " ) )
2020-08-25 06:31:46 -04:00
] ;
Section . AddEntry ( FToolMenuEntry : : InitWidget ( " SetBreakLevels " , MenuWidget , FText : : GetEmpty ( ) , false ) ) ;
}
}
2022-06-17 14:13:33 -04:00
void CreateBreakMenu ( UToolMenu * Menu )
2020-08-25 06:31:46 -04:00
{
2022-06-17 14:13:33 -04:00
if ( ULevelInstanceSubsystem * LevelInstanceSubsystem = GEditor - > GetEditorWorldContext ( ) . World ( ) - > GetSubsystem < ULevelInstanceSubsystem > ( ) )
2020-08-25 06:31:46 -04:00
{
2022-06-17 14:13:33 -04:00
TArray < ILevelInstanceInterface * > BreakableLevelInstances ;
if ( GEditor - > GetSelectedActorCount ( ) > 0 )
2022-03-29 09:19:22 -04:00
{
2022-06-17 14:13:33 -04:00
for ( FSelectionIterator It ( GEditor - > GetSelectedActorIterator ( ) ) ; It ; + + It )
2020-08-25 06:31:46 -04:00
{
2022-06-17 14:13:33 -04:00
if ( ILevelInstanceInterface * LevelInstance = Cast < ILevelInstanceInterface > ( * It ) )
{
if ( IsExperimentalSettingEnabled ( LevelInstance ) & & ! LevelInstanceSubsystem - > IsEditingLevelInstance ( LevelInstance ) & & ! LevelInstanceSubsystem - > LevelInstanceHasLevelScriptBlueprint ( LevelInstance ) )
{
BreakableLevelInstances . Add ( LevelInstance ) ;
}
}
2022-03-29 09:19:22 -04:00
}
2022-06-17 14:13:33 -04:00
}
2020-08-25 06:31:46 -04:00
2022-06-17 14:13:33 -04:00
if ( BreakableLevelInstances . Num ( ) )
2020-08-25 06:31:46 -04:00
{
2021-12-09 08:09:34 -05:00
FToolMenuSection & Section = CreateLevelSection ( Menu ) ;
2020-08-25 06:31:46 -04:00
Section . AddSubMenu (
" BreakLevelInstances " ,
LOCTEXT ( " BreakLevelInstances " , " Break... " ) ,
TAttribute < FText > ( ) ,
2022-06-17 14:13:33 -04:00
FNewToolMenuDelegate : : CreateStatic ( & CreateBreakSubMenu , BreakableLevelInstances )
2020-08-25 06:31:46 -04:00
) ;
}
}
2022-06-17 14:13:33 -04:00
2020-08-25 06:31:46 -04:00
}
2020-11-16 08:50:22 -04:00
void CreatePackedBlueprintMenu ( UToolMenu * Menu , AActor * ContextActor )
{
if ( ULevelInstanceSubsystem * LevelInstanceSubsystem = ContextActor - > GetWorld ( ) - > GetSubsystem < ULevelInstanceSubsystem > ( ) )
{
2022-03-29 09:19:22 -04:00
ILevelInstanceInterface * ContextLevelInstance = nullptr ;
2020-11-16 08:50:22 -04:00
// Find the top level LevelInstance
2022-03-29 09:19:22 -04:00
LevelInstanceSubsystem - > ForEachLevelInstanceAncestorsAndSelf ( ContextActor , [ LevelInstanceSubsystem , ContextActor , & ContextLevelInstance ] ( ILevelInstanceInterface * Ancestor )
2020-11-16 08:50:22 -04:00
{
2022-03-29 09:19:22 -04:00
if ( CastChecked < AActor > ( Ancestor ) - > GetLevel ( ) = = ContextActor - > GetWorld ( ) - > GetCurrentLevel ( ) )
2020-11-16 08:50:22 -04:00
{
ContextLevelInstance = Ancestor ;
return false ;
}
return true ;
} ) ;
2022-01-07 11:45:52 -05:00
if ( ContextLevelInstance & & IsExperimentalSettingEnabled ( ContextLevelInstance ) & & ! ContextLevelInstance - > IsEditing ( ) )
2020-11-16 08:50:22 -04:00
{
2021-12-09 08:09:34 -05:00
FToolMenuSection & Section = CreateLevelSection ( Menu ) ;
;
if ( APackedLevelActor * PackedLevelActor = Cast < APackedLevelActor > ( ContextLevelInstance ) )
2020-11-16 08:50:22 -04:00
{
2023-05-16 10:52:49 -04:00
if ( TSoftObjectPtr < UBlueprint > BlueprintAsset = PackedLevelActor - > GetClass ( ) - > ClassGeneratedBy . Get ( ) )
2021-12-09 08:09:34 -05:00
{
FToolUIAction UIAction ;
UIAction . ExecuteAction . BindLambda ( [ ContextLevelInstance , BlueprintAsset ] ( const FToolMenuContext & MenuContext )
2023-06-14 06:25:37 -04:00
{
FPackedLevelActorUtils : : CreateOrUpdateBlueprint ( ContextLevelInstance - > GetWorldAsset ( ) , BlueprintAsset ) ;
} ) ;
2021-12-09 08:09:34 -05:00
UIAction . CanExecuteAction . BindLambda ( [ ] ( const FToolMenuContext & MenuContext )
2023-06-14 06:25:37 -04:00
{
return FPackedLevelActorUtils : : CanPack ( ) & & GEditor - > GetSelectedActorCount ( ) > 0 ;
} ) ;
2020-11-16 08:50:22 -04:00
2021-12-09 08:09:34 -05:00
Section . AddMenuEntry (
" UpdatePackedBlueprint " ,
LOCTEXT ( " UpdatePackedBlueprint " , " Update Packed Blueprint " ) ,
TAttribute < FText > ( ) ,
TAttribute < FSlateIcon > ( ) ,
UIAction ) ;
}
2020-11-16 08:50:22 -04:00
}
}
}
}
2020-08-25 06:31:46 -04:00
class FLevelInstanceClassFilter : public IClassViewerFilter
{
public :
virtual bool IsClassAllowed ( const FClassViewerInitializationOptions & InInitOptions , const UClass * InClass , TSharedRef < FClassViewerFilterFuncs > InFilterFuncs ) override
{
2023-05-19 13:51:16 -04:00
return InClass & & InClass - > ImplementsInterface ( ULevelInstanceInterface : : StaticClass ( ) ) & & InClass - > IsNative ( ) & & ! InClass - > HasAnyClassFlags ( CLASS_Deprecated ) ;
2020-08-25 06:31:46 -04:00
}
virtual bool IsUnloadedClassAllowed ( const FClassViewerInitializationOptions & InInitOptions , const TSharedRef < const IUnloadedBlueprintData > InUnloadedClassData , TSharedRef < FClassViewerFilterFuncs > InFilterFuncs ) override
{
2023-05-19 13:51:16 -04:00
return false ;
2020-08-25 06:31:46 -04:00
}
} ;
void CreateBlueprintFromWorld ( UWorld * WorldAsset )
{
TSoftObjectPtr < UWorld > LevelInstancePtr ( WorldAsset ) ;
int32 LastSlashIndex = 0 ;
FString LongPackageName = LevelInstancePtr . GetLongPackageName ( ) ;
LongPackageName . FindLastChar ( ' / ' , LastSlashIndex ) ;
FString PackagePath = LongPackageName . Mid ( 0 , LastSlashIndex = = INDEX_NONE ? MAX_int32 : LastSlashIndex ) ;
2023-05-19 13:51:16 -04:00
FString AssetName = " BP_ " + LevelInstancePtr . GetAssetName ( ) ;
2020-08-25 06:31:46 -04:00
IAssetTools & AssetTools = FAssetToolsModule : : GetModule ( ) . Get ( ) ;
UBlueprintFactory * BlueprintFactory = NewObject < UBlueprintFactory > ( ) ;
BlueprintFactory - > AddToRoot ( ) ;
BlueprintFactory - > OnConfigurePropertiesDelegate . BindLambda ( [ ] ( FClassViewerInitializationOptions * Options )
{
Options - > bShowDefaultClasses = false ;
Options - > bIsBlueprintBaseOnly = false ;
Options - > InitiallySelectedClass = ALevelInstance : : StaticClass ( ) ;
Options - > bIsActorsOnly = true ;
2021-06-10 10:40:50 -04:00
Options - > ClassFilters . Add ( MakeShareable ( new FLevelInstanceClassFilter ) ) ;
2020-08-25 06:31:46 -04:00
} ) ;
ON_SCOPE_EXIT
{
BlueprintFactory - > OnConfigurePropertiesDelegate . Unbind ( ) ;
BlueprintFactory - > RemoveFromRoot ( ) ;
} ;
if ( UBlueprint * NewBlueprint = Cast < UBlueprint > ( AssetTools . CreateAssetWithDialog ( AssetName , PackagePath , UBlueprint : : StaticClass ( ) , BlueprintFactory , FName ( " Create LevelInstance Blueprint " ) ) ) )
{
2022-03-29 09:19:22 -04:00
AActor * CDO = NewBlueprint - > GeneratedClass - > GetDefaultObject < AActor > ( ) ;
ILevelInstanceInterface * LevelInstanceCDO = CastChecked < ILevelInstanceInterface > ( CDO ) ;
LevelInstanceCDO - > SetWorldAsset ( LevelInstancePtr ) ;
2020-08-25 06:31:46 -04:00
FBlueprintEditorUtils : : MarkBlueprintAsModified ( NewBlueprint ) ;
2023-05-19 13:51:16 -04:00
if ( NewBlueprint - > GeneratedClass - > IsChildOf < APackedLevelActor > ( ) )
{
2023-06-14 06:25:37 -04:00
FPackedLevelActorUtils : : UpdateBlueprint ( NewBlueprint ) ;
2023-05-19 13:51:16 -04:00
}
2020-08-25 06:31:46 -04:00
FContentBrowserModule & ContentBrowserModule = FModuleManager : : LoadModuleChecked < FContentBrowserModule > ( " ContentBrowser " ) ;
TArray < UObject * > Assets ;
Assets . Add ( NewBlueprint ) ;
ContentBrowserModule . Get ( ) . SyncBrowserToAssets ( Assets ) ;
}
}
2022-10-14 16:59:41 -04:00
void CreateBlueprintFromMenu ( UToolMenu * Menu , FAssetData WorldAsset )
2020-08-25 06:31:46 -04:00
{
2021-12-09 08:09:34 -05:00
FToolMenuSection & Section = CreateLevelSection ( Menu ) ;
2020-08-25 06:31:46 -04:00
FToolUIAction UIAction ;
UIAction . ExecuteAction . BindLambda ( [ WorldAsset ] ( const FToolMenuContext & MenuContext )
{
2022-10-14 16:59:41 -04:00
if ( UWorld * World = Cast < UWorld > ( WorldAsset . GetAsset ( ) ) )
{
CreateBlueprintFromWorld ( World ) ;
}
2020-08-25 06:31:46 -04:00
} ) ;
Section . AddMenuEntry (
" CreateLevelInstanceBlueprint " ,
LOCTEXT ( " CreateLevelInstanceBlueprint " , " New Blueprint... " ) ,
TAttribute < FText > ( ) ,
2023-06-14 06:25:37 -04:00
FSlateIcon ( FAppStyle : : GetAppStyleSetName ( ) , " ClassIcon.LevelInstance " ) ,
2020-08-25 06:31:46 -04:00
UIAction ) ;
}
2022-08-31 08:51:11 -04:00
void AddPartitionedStreamingSupportFromWorld ( UWorld * WorldAsset )
{
2022-09-14 07:32:55 -04:00
if ( WorldAsset - > GetStreamingLevels ( ) . Num ( ) )
{
FMessageDialog : : Open ( EAppMsgType : : Ok , LOCTEXT ( " AddPartitionedLevelInstanceStreamingSupportError_SubLevels " , " Cannot convert this world has it contains sublevels. " ) ) ;
return ;
}
2022-08-31 08:51:11 -04:00
2022-09-14 07:32:55 -04:00
if ( WorldAsset - > WorldType ! = EWorldType : : Inactive )
{
FMessageDialog : : Open ( EAppMsgType : : Ok , LOCTEXT ( " AddPartitionedLevelInstanceStreamingSupportError_Loaded " , " Cannot convert this world has it's already loaded in the editor. " ) ) ;
return ;
}
bool bSuccess = false ;
2022-08-31 08:51:11 -04:00
UWorld * World = GEditor - > GetEditorWorldContext ( ) . World ( ) ;
2022-09-15 18:06:19 -04:00
ULevelInstanceSubsystem : : ResetLoadersForWorldAsset ( WorldAsset - > GetPackage ( ) - > GetName ( ) ) ;
FWorldPartitionConverter : : FParameters Parameters ;
Parameters . bConvertSubLevels = false ;
Parameters . bEnableStreaming = false ;
Parameters . bUseActorFolders = true ;
if ( FWorldPartitionConverter : : Convert ( WorldAsset , Parameters ) )
2022-08-31 08:51:11 -04:00
{
2022-09-15 18:06:19 -04:00
TArray < UPackage * > PackagesToSave = WorldAsset - > PersistentLevel - > GetLoadedExternalObjectPackages ( ) ;
TSet < UPackage * > PackagesToSaveSet ( PackagesToSave ) ;
2022-08-31 08:51:11 -04:00
2022-09-15 18:06:19 -04:00
PackagesToSaveSet . Add ( WorldAsset - > GetPackage ( ) ) ;
2022-08-31 08:51:11 -04:00
2022-09-15 18:06:19 -04:00
const bool bPromptUserToSave = false ;
const bool bSaveMapPackages = true ;
const bool bSaveContentPackages = true ;
const bool bFastSave = false ;
const bool bNotifyNoPackagesSaved = false ;
const bool bCanBeDeclined = true ;
if ( FEditorFileUtils : : SaveDirtyPackages ( bPromptUserToSave , bSaveMapPackages , bSaveContentPackages , bFastSave , bNotifyNoPackagesSaved , bCanBeDeclined , nullptr , [ & PackagesToSaveSet ] ( UPackage * PackageToSave ) { return ! PackagesToSaveSet . Contains ( PackageToSave ) ; } ) )
2022-08-31 08:51:11 -04:00
{
2022-09-15 18:06:19 -04:00
bSuccess = true ;
for ( UPackage * PackageToSave : PackagesToSave )
2022-08-31 08:51:11 -04:00
{
2022-09-15 18:06:19 -04:00
if ( PackageToSave - > IsDirty ( ) )
2022-08-31 08:51:11 -04:00
{
2022-09-15 18:06:19 -04:00
UE_LOG ( LogLevelInstanceEditor , Error , TEXT ( " Package '%s' failed to save " ) , * PackageToSave - > GetName ( ) ) ;
bSuccess = false ;
break ;
2022-08-31 08:51:11 -04:00
}
}
}
}
if ( ! bSuccess )
{
FMessageDialog : : Open ( EAppMsgType : : Ok , LOCTEXT ( " AddPartitionedLevelInstanceStreamingSupportError " , " An error occured when adding partitioned level instance streaming support, check logs for details.. " ) ) ;
}
}
2023-06-14 06:25:37 -04:00
void UpdatePackedBlueprintsFromMenu ( UToolMenu * Menu , FAssetData WorldAsset )
{
FToolMenuSection & Section = CreateLevelSection ( Menu ) ;
FToolUIAction UIAction ;
UIAction . CanExecuteAction . BindLambda ( [ ] ( const FToolMenuContext & MenuContext )
{
return FPackedLevelActorUtils : : CanPack ( ) ;
} ) ;
UIAction . ExecuteAction . BindLambda ( [ WorldAsset ] ( const FToolMenuContext & MenuContext )
{
FScopedSlowTask SlowTask ( 0.0f , LOCTEXT ( " UpdatePackedBlueprintsProgress " , " Updating Packed Blueprints... " ) ) ;
TSet < TSoftObjectPtr < UBlueprint > > BlueprintAssets ;
FPackedLevelActorUtils : : GetPackedBlueprintsForWorldAsset ( TSoftObjectPtr < UWorld > ( WorldAsset . GetSoftObjectPath ( ) ) , BlueprintAssets , false ) ;
2023-06-22 13:32:10 -04:00
TSharedPtr < FPackedLevelActorBuilder > Builder = FPackedLevelActorBuilder : : CreateDefaultBuilder ( ) ;
2023-06-14 06:25:37 -04:00
for ( TSoftObjectPtr < UBlueprint > BlueprintAsset : BlueprintAssets )
{
if ( UBlueprint * Blueprint = BlueprintAsset . Get ( ) )
{
2023-06-22 13:32:10 -04:00
Builder - > UpdateBlueprint ( Blueprint , false ) ;
2023-06-14 06:25:37 -04:00
}
}
} ) ;
Section . AddMenuEntry (
" UpdatePackedBlueprintsFromMenu " ,
LOCTEXT ( " UpdatePackedBlueprintsFromMenu " , " Update Packed Blueprints " ) ,
TAttribute < FText > ( ) ,
FSlateIcon ( FAppStyle : : GetAppStyleSetName ( ) , " ClassIcon.PackedLevelActor " ) ,
UIAction
) ;
}
2022-10-14 16:59:41 -04:00
void AddPartitionedStreamingSupportFromMenu ( UToolMenu * Menu , FAssetData WorldAsset )
2022-08-31 08:51:11 -04:00
{
2022-10-14 16:59:41 -04:00
FName WorldAssetName = WorldAsset . PackageName ;
2023-06-12 07:30:42 -04:00
if ( ! ULevel : : GetIsLevelPartitionedFromPackage ( WorldAssetName ) )
2022-08-31 08:51:11 -04:00
{
FToolMenuSection & Section = CreateLevelSection ( Menu ) ;
FToolUIAction UIAction ;
UIAction . ExecuteAction . BindLambda ( [ WorldAsset ] ( const FToolMenuContext & MenuContext )
{
2022-10-14 16:59:41 -04:00
if ( UWorld * World = Cast < UWorld > ( WorldAsset . GetAsset ( ) ) )
{
AddPartitionedStreamingSupportFromWorld ( World ) ;
}
2022-08-31 08:51:11 -04:00
} ) ;
Section . AddMenuEntry (
" AddPartitionedStreamingSupportFromMenu " ,
LOCTEXT ( " AddPartitionedStreamingSupportFromMenu " , " Add Partitioned Streaming Support " ) ,
TAttribute < FText > ( ) ,
TAttribute < FSlateIcon > ( ) ,
UIAction
) ;
}
}
2020-08-25 06:31:46 -04:00
} ;
void FLevelInstanceEditorModule : : StartupModule ( )
{
ExtendContextMenu ( ) ;
FPropertyEditorModule & PropertyModule = FModuleManager : : LoadModuleChecked < FPropertyEditorModule > ( " PropertyEditor " ) ;
2020-09-11 17:06:48 -04:00
PropertyModule . RegisterCustomClassLayout ( " LevelInstance " , FOnGetDetailCustomizationInstance : : CreateStatic ( & FLevelInstanceActorDetails : : MakeInstance ) ) ;
2023-03-08 12:02:09 -05:00
PropertyModule . RegisterCustomClassLayout ( " LevelInstancePivot " , FOnGetDetailCustomizationInstance : : CreateStatic ( & FLevelInstancePivotDetails : : MakeInstance ) ) ;
2023-06-08 10:14:43 -04:00
PropertyModule . RegisterCustomPropertyTypeLayout ( " WorldPartitionActorFilter " , FOnGetPropertyTypeCustomizationInstance : : CreateStatic ( & FLevelInstanceFilterPropertyTypeCustomization : : MakeInstance , false ) , MakeShared < FLevelInstancePropertyTypeIdentifier > ( false ) ) ;
PropertyModule . RegisterCustomPropertyTypeLayout ( " WorldPartitionActorFilter " , FOnGetPropertyTypeCustomizationInstance : : CreateStatic ( & FLevelInstanceFilterPropertyTypeCustomization : : MakeInstance , true ) , MakeShared < FLevelInstancePropertyTypeIdentifier > ( true ) ) ;
2020-08-25 06:31:46 -04:00
PropertyModule . NotifyCustomizationModuleChanged ( ) ;
// GEditor needs to be set before this module is loaded
check ( GEditor ) ;
GEditor - > OnLevelActorDeleted ( ) . AddRaw ( this , & FLevelInstanceEditorModule : : OnLevelActorDeleted ) ;
EditorLevelUtils : : CanMoveActorToLevelDelegate . AddRaw ( this , & FLevelInstanceEditorModule : : CanMoveActorToLevel ) ;
2023-03-08 12:02:09 -05:00
// Register actor descriptor loading filter
2023-03-10 11:01:34 -05:00
class FLevelInstanceActorDescFilter : public IWorldPartitionActorLoaderInterface : : FActorDescFilter
{
public :
bool PassFilter ( class UWorld * InWorld , const FWorldPartitionHandle & InHandle ) override
2023-03-08 12:02:09 -05:00
{
2023-03-10 11:01:34 -05:00
if ( UWorld * OwningWorld = InWorld - > PersistentLevel - > GetWorld ( ) )
2023-03-08 12:02:09 -05:00
{
2023-03-10 11:01:34 -05:00
if ( ULevelInstanceSubsystem * LevelInstanceSubsystem = OwningWorld - > GetSubsystem < ULevelInstanceSubsystem > ( ) )
{
return LevelInstanceSubsystem - > PassLevelInstanceFilter ( InWorld , InHandle ) ;
}
2023-03-08 12:02:09 -05:00
}
2023-03-10 11:01:34 -05:00
return true ;
2023-03-08 12:02:09 -05:00
}
2023-03-10 11:01:34 -05:00
// Leave [0, 19] for Game code
virtual uint32 GetFilterPriority ( ) const override { return 20 ; }
virtual FText * GetFilterReason ( ) const override
{
static FText UnloadedReason ( LOCTEXT ( " LevelInstanceActorDescFilterReason " , " Filtered " ) ) ;
return & UnloadedReason ;
}
} ;
IWorldPartitionActorLoaderInterface : : RegisterActorDescFilter ( MakeShareable < IWorldPartitionActorLoaderInterface : : FActorDescFilter > ( new FLevelInstanceActorDescFilter ( ) ) ) ;
2023-03-08 12:02:09 -05:00
2020-11-16 08:50:22 -04:00
FMessageLogModule & MessageLogModule = FModuleManager : : LoadModuleChecked < FMessageLogModule > ( " MessageLog " ) ;
FMessageLogInitializationOptions InitOptions ;
InitOptions . bShowFilters = true ;
InitOptions . bShowPages = false ;
InitOptions . bAllowClear = true ;
2022-01-31 10:19:20 -05:00
MessageLogModule . RegisterLogListing ( " PackedLevelActor " , LOCTEXT ( " PackedLevelActorLog " , " Packed Level Actor Log " ) , InitOptions ) ;
2021-11-29 14:47:15 -05:00
FLevelInstanceEditorModeCommands : : Register ( ) ;
if ( ! IsRunningCommandlet ( ) )
{
GLevelEditorModeTools ( ) . OnEditorModeIDChanged ( ) . AddRaw ( this , & FLevelInstanceEditorModule : : OnEditorModeIDChanged ) ;
}
2020-08-25 06:31:46 -04:00
}
void FLevelInstanceEditorModule : : ShutdownModule ( )
{
if ( GEditor )
{
GEditor - > OnLevelActorDeleted ( ) . RemoveAll ( this ) ;
}
EditorLevelUtils : : CanMoveActorToLevelDelegate . RemoveAll ( this ) ;
2021-11-29 14:47:15 -05:00
if ( ! IsRunningCommandlet ( ) & & GLevelEditorModeToolsIsValid ( ) )
2020-08-25 06:31:46 -04:00
{
2021-11-29 14:47:15 -05:00
GLevelEditorModeTools ( ) . OnEditorModeIDChanged ( ) . RemoveAll ( this ) ;
}
}
void FLevelInstanceEditorModule : : OnEditorModeIDChanged ( const FEditorModeID & InModeID , bool bIsEnteringMode )
{
if ( InModeID = = ULevelInstanceEditorMode : : EM_LevelInstanceEditorModeId & & ! bIsEnteringMode )
{
ExitEditorModeEvent . Broadcast ( ) ;
}
}
2022-01-13 11:53:38 -05:00
void FLevelInstanceEditorModule : : BroadcastTryExitEditorMode ( )
{
TryExitEditorModeEvent . Broadcast ( ) ;
}
2021-11-29 14:47:15 -05:00
void FLevelInstanceEditorModule : : ActivateEditorMode ( )
{
if ( ! GLevelEditorModeTools ( ) . IsModeActive ( ULevelInstanceEditorMode : : EM_LevelInstanceEditorModeId ) )
{
GLevelEditorModeTools ( ) . ActivateMode ( ULevelInstanceEditorMode : : EM_LevelInstanceEditorModeId ) ;
}
}
void FLevelInstanceEditorModule : : DeactivateEditorMode ( )
{
if ( GLevelEditorModeTools ( ) . IsModeActive ( ULevelInstanceEditorMode : : EM_LevelInstanceEditorModeId ) )
{
GLevelEditorModeTools ( ) . DeactivateMode ( ULevelInstanceEditorMode : : EM_LevelInstanceEditorModeId ) ;
2020-08-25 06:31:46 -04:00
}
}
void FLevelInstanceEditorModule : : OnLevelActorDeleted ( AActor * Actor )
{
if ( ULevelInstanceSubsystem * LevelInstanceSubsystem = Actor - > GetWorld ( ) - > GetSubsystem < ULevelInstanceSubsystem > ( ) )
{
LevelInstanceSubsystem - > OnActorDeleted ( Actor ) ;
}
}
void FLevelInstanceEditorModule : : CanMoveActorToLevel ( const AActor * ActorToMove , const ULevel * DestLevel , bool & bOutCanMove )
{
if ( UWorld * World = ActorToMove - > GetWorld ( ) )
{
if ( ULevelInstanceSubsystem * LevelInstanceSubsystem = World - > GetSubsystem < ULevelInstanceSubsystem > ( ) )
{
if ( ! LevelInstanceSubsystem - > CanMoveActorToLevel ( ActorToMove ) )
{
bOutCanMove = false ;
return ;
}
}
}
}
void FLevelInstanceEditorModule : : ExtendContextMenu ( )
{
2020-11-16 08:50:22 -04:00
if ( UToolMenu * BuildMenu = UToolMenus : : Get ( ) - > ExtendMenu ( " LevelEditor.MainMenu.Build " ) )
{
2021-12-09 08:09:34 -05:00
FToolMenuSection & Section = BuildMenu - > AddSection ( " LevelEditorLevelInstance " , LOCTEXT ( " PackedLevelActorsHeading " , " Packed Level Actor " ) ) ;
2020-11-16 08:50:22 -04:00
FUIAction PackAction (
FExecuteAction : : CreateLambda ( [ ] ( )
{
2023-06-14 06:25:37 -04:00
FPackedLevelActorUtils : : PackAllLoadedActors ( ) ;
2020-11-16 08:50:22 -04:00
} ) ,
FCanExecuteAction : : CreateLambda ( [ ] ( )
{
2023-06-14 06:25:37 -04:00
return FPackedLevelActorUtils : : CanPack ( ) ;
2022-01-07 11:45:52 -05:00
} ) ,
FIsActionChecked ( ) ,
FIsActionButtonVisible : : CreateLambda ( [ ] ( )
{
return GetDefault < UEditorExperimentalSettings > ( ) - > bPackedLevelActor ;
2020-11-16 08:50:22 -04:00
} ) ) ;
2021-12-09 08:09:34 -05:00
FToolMenuEntry & Entry = Section . AddMenuEntry ( NAME_None , LOCTEXT ( " PackLevelActorsTitle " , " Pack Level Actors " ) ,
LOCTEXT ( " PackLevelActorsTooltip " , " Update packed level actor blueprints " ) , FSlateIcon ( ) , PackAction , EUserInterfaceActionType : : Button ) ;
2020-11-16 08:50:22 -04:00
}
2021-12-09 08:09:34 -05:00
auto AddDynamicSection = [ ] ( UToolMenu * ToolMenu )
{
2023-06-14 06:25:37 -04:00
if ( GEditor - > GetPIEWorldContext ( ) )
{
return ;
}
2021-12-09 08:09:34 -05:00
if ( ULevelEditorContextMenuContext * LevelEditorMenuContext = ToolMenu - > Context . FindContext < ULevelEditorContextMenuContext > ( ) )
2020-08-25 06:31:46 -04:00
{
2021-12-09 08:09:34 -05:00
// Use the actor under the cursor if available (e.g. right-click menu).
// Otherwise use the first selected actor if there's one (e.g. Actor pulldown menu or outliner).
2022-06-29 16:22:54 -04:00
AActor * ContextActor = LevelEditorMenuContext - > HitProxyActor . Get ( ) ;
2021-12-09 08:09:34 -05:00
if ( ! ContextActor & & GEditor - > GetSelectedActorCount ( ) ! = 0 )
2020-08-25 06:31:46 -04:00
{
2021-12-09 08:09:34 -05:00
ContextActor = Cast < AActor > ( GEditor - > GetSelectedActors ( ) - > GetSelectedObject ( 0 ) ) ;
2020-08-25 06:31:46 -04:00
}
2021-12-09 08:09:34 -05:00
if ( ContextActor )
{
LevelInstanceMenuUtils : : CreateEditMenu ( ToolMenu , ContextActor ) ;
2022-01-04 07:28:59 -05:00
LevelInstanceMenuUtils : : CreateCommitDiscardMenu ( ToolMenu , ContextActor ) ;
2021-12-09 08:09:34 -05:00
LevelInstanceMenuUtils : : CreatePackedBlueprintMenu ( ToolMenu , ContextActor ) ;
2022-01-26 15:37:41 -05:00
LevelInstanceMenuUtils : : CreateSetCurrentMenu ( ToolMenu , ContextActor ) ;
2021-12-09 08:09:34 -05:00
}
LevelInstanceMenuUtils : : CreateMoveSelectionToMenu ( ToolMenu ) ;
}
2022-06-17 14:13:33 -04:00
LevelInstanceMenuUtils : : CreateBreakMenu ( ToolMenu ) ;
2021-12-09 08:09:34 -05:00
LevelInstanceMenuUtils : : CreateCreateMenu ( ToolMenu ) ;
} ;
if ( UToolMenu * ToolMenu = UToolMenus : : Get ( ) - > ExtendMenu ( " LevelEditor.ActorContextMenu.LevelSubMenu " ) )
{
ToolMenu - > AddDynamicSection ( " LevelInstanceEditorModuleDynamicSection " , FNewToolMenuDelegate : : CreateLambda ( AddDynamicSection ) ) ;
2020-08-25 06:31:46 -04:00
}
2021-12-09 08:09:34 -05:00
if ( UToolMenu * ToolMenu = UToolMenus : : Get ( ) - > ExtendMenu ( " LevelEditor.LevelEditorSceneOutliner.ContextMenu.LevelSubMenu " ) )
{
ToolMenu - > AddDynamicSection ( " LevelInstanceEditorModuleDynamicSection " , FNewToolMenuDelegate : : CreateLambda ( AddDynamicSection ) ) ;
}
2020-08-25 06:31:46 -04:00
if ( UToolMenu * WorldAssetMenu = UToolMenus : : Get ( ) - > ExtendMenu ( " ContentBrowser.AssetContextMenu.World " ) )
{
FToolMenuSection & Section = WorldAssetMenu - > AddDynamicSection ( " ActorLevelInstance " , FNewToolMenuDelegate : : CreateLambda ( [ this ] ( UToolMenu * ToolMenu )
{
2023-06-14 06:25:37 -04:00
if ( GEditor - > GetPIEWorldContext ( ) )
{
return ;
}
2022-01-07 11:45:52 -05:00
if ( ! GetDefault < UEditorExperimentalSettings > ( ) - > bLevelInstance )
{
return ;
}
2020-08-25 06:31:46 -04:00
if ( ToolMenu )
{
if ( UContentBrowserAssetContextMenuContext * AssetMenuContext = ToolMenu - > Context . FindContext < UContentBrowserAssetContextMenuContext > ( ) )
{
2022-10-14 16:59:41 -04:00
if ( AssetMenuContext - > SelectedAssets . Num ( ) ! = 1 )
2020-08-25 06:31:46 -04:00
{
return ;
}
2022-10-14 16:59:41 -04:00
const FAssetData & WorldAsset = AssetMenuContext - > SelectedAssets [ 0 ] ;
if ( AssetMenuContext - > SelectedAssets [ 0 ] . IsInstanceOf < UWorld > ( ) )
2020-08-25 06:31:46 -04:00
{
LevelInstanceMenuUtils : : CreateBlueprintFromMenu ( ToolMenu , WorldAsset ) ;
2023-06-14 06:25:37 -04:00
LevelInstanceMenuUtils : : UpdatePackedBlueprintsFromMenu ( ToolMenu , WorldAsset ) ;
2022-08-31 08:51:11 -04:00
LevelInstanceMenuUtils : : AddPartitionedStreamingSupportFromMenu ( ToolMenu , WorldAsset ) ;
2020-08-25 06:31:46 -04:00
}
}
}
} ) , FToolMenuInsert ( NAME_None , EToolMenuInsertType : : Default ) ) ;
}
}
# undef LOCTEXT_NAMESPACE