2014-12-07 19:09:38 -05:00
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
2014-03-14 14:13:41 -04:00
# include "ContentBrowserPCH.h"
# include "AssetViewTypes.h"
# include "AssetContextMenu.h"
# include "ContentBrowserModule.h"
# include "Editor/UnrealEd/Public/ObjectTools.h"
# include "Editor/UnrealEd/Public/PackageTools.h"
# include "Editor/UnrealEd/Public/FileHelpers.h"
# include "Editor/PropertyEditor/Public/PropertyEditorModule.h"
# include "Toolkits/AssetEditorManager.h"
2014-06-25 13:25:21 -04:00
# include "Toolkits/ToolkitManager.h"
2014-03-14 14:13:41 -04:00
# include "ConsolidateWindow.h"
# include "ReferenceViewer.h"
2015-04-22 15:58:21 -04:00
# include "ISizeMapModule.h"
2014-03-14 14:13:41 -04:00
# include "ReferencedAssetsUtils.h"
# include "ISourceControlModule.h"
# include "ISourceControlRevision.h"
# include "SourceControlWindows.h"
# include "KismetEditorUtilities.h"
# include "AssetToolsModule.h"
# include "ComponentAssetBroker.h"
2014-08-07 17:34:29 -04:00
# include "SNumericEntryBox.h"
2014-03-14 14:13:41 -04:00
2014-07-30 17:50:36 -04:00
# include "SourceCodeNavigation.h"
# include "IDocumentation.h"
# include "EditorClassUtils.h"
2014-08-27 20:35:19 -04:00
# include "SColorPicker.h"
2014-10-14 22:50:06 -04:00
# include "GenericCommands.h"
# include "SNotificationList.h"
# include "NotificationManager.h"
2014-11-12 04:58:53 -05:00
# include "Engine/LevelStreaming.h"
2014-08-27 20:35:19 -04:00
2014-03-14 14:13:41 -04:00
# define LOCTEXT_NAMESPACE "ContentBrowser"
FAssetContextMenu : : FAssetContextMenu ( const TWeakPtr < SAssetView > & InAssetView )
2014-07-30 14:51:27 -04:00
: AssetView ( InAssetView )
, bAtLeastOneNonRedirectorSelected ( false )
2015-01-16 15:39:47 -05:00
, bAtLeastOneClassSelected ( false )
2014-10-28 22:59:51 -04:00
, bCanExecuteSCCMerge ( false )
2014-03-14 14:13:41 -04:00
, bCanExecuteSCCCheckOut ( false )
, bCanExecuteSCCOpenForAdd ( false )
, bCanExecuteSCCCheckIn ( false )
, bCanExecuteSCCHistory ( false )
, bCanExecuteSCCRevert ( false )
, bCanExecuteSCCSync ( false )
{
2014-10-09 12:35:10 -04:00
}
2014-03-14 14:13:41 -04:00
2014-10-09 12:35:10 -04:00
void FAssetContextMenu : : BindCommands ( TSharedPtr < FUICommandList > & Commands )
{
Commands - > MapAction ( FGenericCommands : : Get ( ) . Duplicate , FUIAction (
FExecuteAction : : CreateSP ( this , & FAssetContextMenu : : ExecuteDuplicate ) ,
FCanExecuteAction : : CreateSP ( this , & FAssetContextMenu : : CanExecuteDuplicate ) ,
FIsActionChecked ( ) ,
FIsActionButtonVisible : : CreateSP ( this , & FAssetContextMenu : : CanExecuteDuplicate )
) ) ;
2014-03-14 14:13:41 -04:00
}
TSharedRef < SWidget > FAssetContextMenu : : MakeContextMenu ( const TArray < FAssetData > & InSelectedAssets , const FSourcesData & InSourcesData , TSharedPtr < FUICommandList > InCommandList )
{
2014-10-09 12:35:10 -04:00
SetSelectedAssets ( InSelectedAssets ) ;
2014-03-14 14:13:41 -04:00
SourcesData = InSourcesData ;
// Cache any vars that are used in determining if you can execute any actions.
// Useful for actions whose "CanExecute" will not change or is expensive to calculate.
CacheCanExecuteVars ( ) ;
// Get all menu extenders for this context menu from the content browser module
FContentBrowserModule & ContentBrowserModule = FModuleManager : : GetModuleChecked < FContentBrowserModule > ( TEXT ( " ContentBrowser " ) ) ;
TArray < FContentBrowserMenuExtender_SelectedAssets > MenuExtenderDelegates = ContentBrowserModule . GetAllAssetViewContextMenuExtenders ( ) ;
TArray < TSharedPtr < FExtender > > Extenders ;
for ( int32 i = 0 ; i < MenuExtenderDelegates . Num ( ) ; + + i )
{
if ( MenuExtenderDelegates [ i ] . IsBound ( ) )
{
Extenders . Add ( MenuExtenderDelegates [ i ] . Execute ( SelectedAssets ) ) ;
}
}
TSharedPtr < FExtender > MenuExtender = FExtender : : Combine ( Extenders ) ;
FMenuBuilder MenuBuilder ( /*bInShouldCloseWindowAfterMenuSelection=*/ true , InCommandList , MenuExtender ) ;
// Only add something if at least one asset is selected
if ( SelectedAssets . Num ( ) )
{
// Add any type-specific context menu options
AddAssetTypeMenuOptions ( MenuBuilder ) ;
2014-10-09 12:35:10 -04:00
// Add imported asset context menu options
AddImportedAssetMenuOptions ( MenuBuilder ) ;
2014-03-14 14:13:41 -04:00
// Add quick access to common commands.
AddCommonMenuOptions ( MenuBuilder ) ;
2015-04-23 17:05:53 -04:00
// Add quick access to view commands
AddExploreMenuOptions ( MenuBuilder ) ;
2014-03-14 14:13:41 -04:00
// Add reference options
AddReferenceMenuOptions ( MenuBuilder ) ;
2014-07-30 17:50:36 -04:00
// Add documentation options
AddDocumentationMenuOptions ( MenuBuilder ) ;
2014-03-14 14:13:41 -04:00
// Add collection options
AddCollectionMenuOptions ( MenuBuilder ) ;
2014-10-09 12:35:10 -04:00
// Add source control options
AddSourceControlMenuOptions ( MenuBuilder ) ;
2014-03-14 14:13:41 -04:00
}
return MenuBuilder . MakeWidget ( ) ;
}
2014-10-09 12:35:10 -04:00
void FAssetContextMenu : : SetSelectedAssets ( const TArray < FAssetData > & InSelectedAssets )
{
SelectedAssets = InSelectedAssets ;
}
2014-03-14 14:13:41 -04:00
void FAssetContextMenu : : SetOnFindInAssetTreeRequested ( const FOnFindInAssetTreeRequested & InOnFindInAssetTreeRequested )
{
OnFindInAssetTreeRequested = InOnFindInAssetTreeRequested ;
}
void FAssetContextMenu : : SetOnRenameRequested ( const FOnRenameRequested & InOnRenameRequested )
{
OnRenameRequested = InOnRenameRequested ;
}
void FAssetContextMenu : : SetOnRenameFolderRequested ( const FOnRenameFolderRequested & InOnRenameFolderRequested )
{
OnRenameFolderRequested = InOnRenameFolderRequested ;
}
void FAssetContextMenu : : SetOnDuplicateRequested ( const FOnDuplicateRequested & InOnDuplicateRequested )
{
OnDuplicateRequested = InOnDuplicateRequested ;
}
void FAssetContextMenu : : SetOnAssetViewRefreshRequested ( const FOnAssetViewRefreshRequested & InOnAssetViewRefreshRequested )
{
OnAssetViewRefreshRequested = InOnAssetViewRefreshRequested ;
}
2014-10-09 12:35:10 -04:00
bool FAssetContextMenu : : AddImportedAssetMenuOptions ( FMenuBuilder & MenuBuilder )
{
if ( AreImportedAssetActionsVisible ( ) )
{
TArray < FString > ResolvedFilePaths ;
GetSelectedAssetSourceFilePaths ( ResolvedFilePaths ) ;
MenuBuilder . BeginSection ( " ImportedAssetActions " , LOCTEXT ( " ImportedAssetActionsMenuHeading " , " Imported Asset " ) ) ;
{
// Reimport
MenuBuilder . AddMenuEntry (
LOCTEXT ( " Reimport " , " Reimport " ) ,
LOCTEXT ( " ReimportTooltip " , " Reimport the selected asset(s) from the source file on disk. " ) ,
2015-04-20 00:01:25 -04:00
FSlateIcon ( ) ,
2014-10-09 12:35:10 -04:00
FUIAction (
FExecuteAction : : CreateSP ( this , & FAssetContextMenu : : ExecuteReimport ) ,
FCanExecuteAction ( )
)
) ;
// Show Source In Explorer
MenuBuilder . AddMenuEntry (
LOCTEXT ( " FindSourceFile " , " Open Source Location " ) ,
LOCTEXT ( " FindSourceFileTooltip " , " Opens the folder containing the source of the selected asset(s). " ) ,
2014-11-19 23:55:24 -05:00
FSlateIcon ( FEditorStyle : : GetStyleSetName ( ) , " ContentBrowser.AssetActions.OpenSourceLocation " ) ,
2014-10-09 12:35:10 -04:00
FUIAction (
FExecuteAction : : CreateSP ( this , & FAssetContextMenu : : ExecuteFindSourceInExplorer , ResolvedFilePaths ) ,
FCanExecuteAction : : CreateSP ( this , & FAssetContextMenu : : CanExecuteImportedAssetActions , ResolvedFilePaths )
)
) ;
// Open In External Editor
MenuBuilder . AddMenuEntry (
LOCTEXT ( " OpenInExternalEditor " , " Open In External Editor " ) ,
LOCTEXT ( " OpenInExternalEditorTooltip " , " Open the selected asset(s) in the default external editor. " ) ,
2014-11-19 23:55:24 -05:00
FSlateIcon ( FEditorStyle : : GetStyleSetName ( ) , " ContentBrowser.AssetActions.OpenInExternalEditor " ) ,
2014-10-09 12:35:10 -04:00
FUIAction (
FExecuteAction : : CreateSP ( this , & FAssetContextMenu : : ExecuteOpenInExternalEditor , ResolvedFilePaths ) ,
FCanExecuteAction : : CreateSP ( this , & FAssetContextMenu : : CanExecuteImportedAssetActions , ResolvedFilePaths )
)
) ;
}
MenuBuilder . EndSection ( ) ;
return true ;
}
return false ;
}
2014-03-14 14:13:41 -04:00
bool FAssetContextMenu : : AddCommonMenuOptions ( FMenuBuilder & MenuBuilder )
{
2014-10-09 12:35:10 -04:00
MenuBuilder . BeginSection ( " CommonAssetActions " , LOCTEXT ( " CommonAssetActionsMenuHeading " , " Common " ) ) ;
2014-03-14 14:13:41 -04:00
{
2015-04-23 17:05:53 -04:00
// Edit
MenuBuilder . AddMenuEntry (
LOCTEXT ( " EditAsset " , " Edit... " ) ,
LOCTEXT ( " EditAssetTooltip " , " Opens the selected asset(s) for edit. " ) ,
FSlateIcon ( ) ,
FUIAction ( FExecuteAction : : CreateSP ( this , & FAssetContextMenu : : ExecuteEditAsset ) )
) ;
2014-10-09 12:35:10 -04:00
2015-04-23 17:05:53 -04:00
// Rename
MenuBuilder . AddMenuEntry ( FGenericCommands : : Get ( ) . Rename , NAME_None ,
LOCTEXT ( " Rename " , " Rename " ) ,
LOCTEXT ( " RenameTooltip " , " Rename the selected asset. " ) ,
FSlateIcon ( )
) ;
2014-03-14 14:13:41 -04:00
2015-04-23 17:05:53 -04:00
// Duplicate
MenuBuilder . AddMenuEntry ( FGenericCommands : : Get ( ) . Duplicate , NAME_None ,
LOCTEXT ( " Duplicate " , " Duplicate " ) ,
LOCTEXT ( " DuplicateTooltip " , " Create a copy of the selected asset(s). " ) ,
FSlateIcon ( )
) ;
2014-03-14 14:13:41 -04:00
2015-04-23 17:05:53 -04:00
// Save
MenuBuilder . AddMenuEntry (
LOCTEXT ( " SaveAsset " , " Save " ) ,
LOCTEXT ( " SaveAssetTooltip " , " Saves the asset to file. " ) ,
FSlateIcon ( ) ,
FUIAction (
FExecuteAction : : CreateSP ( this , & FAssetContextMenu : : ExecuteSaveAsset ) ,
FCanExecuteAction : : CreateSP ( this , & FAssetContextMenu : : CanExecuteSaveAsset )
)
) ;
2014-03-14 14:13:41 -04:00
2015-04-23 17:05:53 -04:00
// Delete
MenuBuilder . AddMenuEntry ( FGenericCommands : : Get ( ) . Delete , NAME_None ,
LOCTEXT ( " Delete " , " Delete " ) ,
LOCTEXT ( " DeleteTooltip " , " Delete the selected assets. " ) ,
FSlateIcon ( )
) ;
2014-08-07 17:34:29 -04:00
2015-04-23 17:05:53 -04:00
// Open Containing Folder
MenuBuilder . AddMenuEntry (
LOCTEXT ( " SyncToAssetTree " , " Show in Sources Panel " ) ,
LOCTEXT ( " SyncToAssetTreeTooltip " , " Selects the folder that contains this asset in the Content Browser Sources Panel. " ) ,
FSlateIcon ( ) ,
FUIAction (
FExecuteAction : : CreateSP ( this , & FAssetContextMenu : : ExecuteSyncToAssetTree ) ,
FCanExecuteAction : : CreateSP ( this , & FAssetContextMenu : : CanExecuteSyncToAssetTree )
)
) ;
// Asset Actions sub-menu
MenuBuilder . AddSubMenu (
LOCTEXT ( " AssetActionsSubMenuLabel " , " Asset Actions " ) ,
LOCTEXT ( " AssetActionsSubMenuToolTip " , " Other asset actions " ) ,
FNewMenuDelegate : : CreateSP ( this , & FAssetContextMenu : : MakeAssetActionsSubMenu ) ,
FUIAction (
FExecuteAction ( ) ,
FCanExecuteAction : : CreateSP ( this , & FAssetContextMenu : : CanExecuteAssetActions )
) ,
NAME_None ,
EUserInterfaceActionType : : Button ,
false ,
FSlateIcon ( )
) ;
2014-03-14 14:13:41 -04:00
}
MenuBuilder . EndSection ( ) ;
return true ;
}
2015-04-23 17:05:53 -04:00
void FAssetContextMenu : : AddExploreMenuOptions ( FMenuBuilder & MenuBuilder )
{
MenuBuilder . BeginSection ( " AssetContextExploreMenuOptions " , LOCTEXT ( " AssetContextExploreMenuOptionsHeading " , " Explore " ) ) ;
{
// Open Containing Folder
MenuBuilder . AddMenuEntry (
LOCTEXT ( " SyncToAssetTree " , " Show in Folder View " ) ,
LOCTEXT ( " SyncToAssetTreeTooltip " , " Selects the folder that contains this asset in the Content Browser Sources Panel. " ) ,
FSlateIcon ( ) ,
FUIAction (
FExecuteAction : : CreateSP ( this , & FAssetContextMenu : : ExecuteSyncToAssetTree ) ,
FCanExecuteAction : : CreateSP ( this , & FAssetContextMenu : : CanExecuteSyncToAssetTree )
)
) ;
// Find in Explorer
MenuBuilder . AddMenuEntry (
ContentBrowserUtils : : GetExploreFolderText ( ) ,
LOCTEXT ( " FindInExplorerTooltip " , " Finds this asset on disk " ) ,
FSlateIcon ( ) ,
FUIAction (
FExecuteAction : : CreateSP ( this , & FAssetContextMenu : : ExecuteFindInExplorer ) ,
FCanExecuteAction : : CreateSP ( this , & FAssetContextMenu : : CanExecuteFindInExplorer )
)
) ;
}
MenuBuilder . EndSection ( ) ;
}
2014-10-09 12:35:10 -04:00
void FAssetContextMenu : : MakeAssetActionsSubMenu ( FMenuBuilder & MenuBuilder )
{
// Create BP Using This
MenuBuilder . AddMenuEntry (
LOCTEXT ( " CreateBlueprintUsing " , " Create Blueprint Using This... " ) ,
LOCTEXT ( " CreateBlueprintUsingTooltip " , " Create a new Blueprint and add this asset to it " ) ,
FSlateIcon ( FEditorStyle : : GetStyleSetName ( ) , " LevelEditor.CreateClassBlueprint " ) ,
FUIAction (
FExecuteAction : : CreateSP ( this , & FAssetContextMenu : : ExecuteCreateBlueprintUsing ) ,
FCanExecuteAction : : CreateSP ( this , & FAssetContextMenu : : CanExecuteCreateBlueprintUsing )
)
) ;
// Capture Thumbnail
FAssetToolsModule & AssetToolsModule = FModuleManager : : LoadModuleChecked < FAssetToolsModule > ( " AssetTools " ) ;
if ( SelectedAssets . Num ( ) = = 1 & & AssetToolsModule . Get ( ) . AssetUsesGenericThumbnail ( SelectedAssets [ 0 ] ) )
{
MenuBuilder . AddMenuEntry (
LOCTEXT ( " CaptureThumbnail " , " Capture Thumbnail " ) ,
LOCTEXT ( " CaptureThumbnailTooltip " , " Captures a thumbnail from the active viewport. " ) ,
FSlateIcon ( ) ,
FUIAction (
FExecuteAction : : CreateSP ( this , & FAssetContextMenu : : ExecuteCaptureThumbnail ) ,
FCanExecuteAction : : CreateSP ( this , & FAssetContextMenu : : CanExecuteCaptureThumbnail )
)
) ;
}
// Clear Thumbnail
if ( CanClearCustomThumbnails ( ) )
{
MenuBuilder . AddMenuEntry (
LOCTEXT ( " ClearCustomThumbnail " , " Clear Thumbnail " ) ,
LOCTEXT ( " ClearCustomThumbnailTooltip " , " Clears all custom thumbnails for selected assets. " ) ,
FSlateIcon ( ) ,
FUIAction ( FExecuteAction : : CreateSP ( this , & FAssetContextMenu : : ExecuteClearThumbnail ) )
) ;
}
// FIND ACTIONS
MenuBuilder . BeginSection ( " AssetContextFindActions " , LOCTEXT ( " AssetContextFindActionsMenuHeading " , " Find " ) ) ;
{
// Select Actors Using This Asset
MenuBuilder . AddMenuEntry (
LOCTEXT ( " FindAssetInWorld " , " Select Actors Using This Asset " ) ,
LOCTEXT ( " FindAssetInWorldTooltip " , " Selects all actors referencing this asset. " ) ,
2015-04-02 17:56:43 -04:00
FSlateIcon ( ) ,
2014-10-09 12:35:10 -04:00
FUIAction (
FExecuteAction : : CreateSP ( this , & FAssetContextMenu : : ExecuteFindAssetInWorld ) ,
FCanExecuteAction : : CreateSP ( this , & FAssetContextMenu : : CanExecuteFindAssetInWorld )
)
) ;
}
MenuBuilder . EndSection ( ) ;
// MOVE ACTIONS
MenuBuilder . BeginSection ( " AssetContextMoveActions " , LOCTEXT ( " AssetContextMoveActionsMenuHeading " , " Move " ) ) ;
{
// Export
MenuBuilder . AddMenuEntry (
LOCTEXT ( " Export " , " Export... " ) ,
LOCTEXT ( " ExportTooltip " , " Export the selected assets to file. " ) ,
FSlateIcon ( ) ,
FUIAction ( FExecuteAction : : CreateSP ( this , & FAssetContextMenu : : ExecuteExport ) )
) ;
// Bulk Export
if ( SelectedAssets . Num ( ) > 1 )
{
MenuBuilder . AddMenuEntry (
LOCTEXT ( " BulkExport " , " Bulk Export... " ) ,
LOCTEXT ( " BulkExportTooltip " , " Export the selected assets to file in the selected directory " ) ,
FSlateIcon ( ) ,
FUIAction ( FExecuteAction : : CreateSP ( this , & FAssetContextMenu : : ExecuteBulkExport ) )
) ;
}
// Migrate
MenuBuilder . AddMenuEntry (
LOCTEXT ( " MigrateAsset " , " Migrate... " ) ,
2014-10-30 12:47:09 -04:00
LOCTEXT ( " MigrateAssetTooltip " , " Copies all selected assets and their dependencies to another project " ) ,
2014-10-09 12:35:10 -04:00
FSlateIcon ( ) ,
FUIAction ( FExecuteAction : : CreateSP ( this , & FAssetContextMenu : : ExecuteMigrateAsset ) )
) ;
}
MenuBuilder . EndSection ( ) ;
// ADVANCED ACTIONS
MenuBuilder . BeginSection ( " AssetContextAdvancedActions " , LOCTEXT ( " AssetContextAdvancedActionsMenuHeading " , " Advanced " ) ) ;
{
// Replace References
if ( CanExecuteConsolidate ( ) )
{
MenuBuilder . AddMenuEntry (
LOCTEXT ( " ReplaceReferences " , " Replace References " ) ,
LOCTEXT ( " ConsolidateTooltip " , " Replace references to the selected assets. " ) ,
FSlateIcon ( ) ,
FUIAction (
FExecuteAction : : CreateSP ( this , & FAssetContextMenu : : ExecuteConsolidate )
)
) ;
}
// Property Matrix
2015-04-22 16:46:57 -04:00
bool bCanUsePropertyMatrix = true ;
2015-04-23 17:42:25 -04:00
// Materials can't be bulk edited currently as they require very special handling because of their dependencies with the rendering thread, and we'd have to hack the property matrix too much.
2015-04-22 16:46:57 -04:00
for ( auto & Asset : SelectedAssets )
{
2015-04-23 17:42:25 -04:00
if ( Asset . AssetClass = = UMaterial : : StaticClass ( ) - > GetFName ( ) | | Asset . AssetClass = = UMaterialInstanceConstant : : StaticClass ( ) - > GetFName ( ) | | Asset . AssetClass = = UMaterialFunction : : StaticClass ( ) - > GetFName ( ) )
2015-04-22 16:46:57 -04:00
{
bCanUsePropertyMatrix = false ;
break ;
}
}
if ( bCanUsePropertyMatrix )
{
MenuBuilder . AddMenuEntry (
LOCTEXT ( " PropertyMatrix " , " Bulk Edit via Property Matrix... " ) ,
LOCTEXT ( " PropertyMatrixTooltip " , " Opens the property matrix editor for the selected assets. " ) ,
FSlateIcon ( ) ,
FUIAction (
FExecuteAction : : CreateSP ( this , & FAssetContextMenu : : ExecutePropertyMatrix ) ,
FCanExecuteAction : : CreateSP ( this , & FAssetContextMenu : : CanExecuteProperties )
)
) ;
}
2014-10-09 12:35:10 -04:00
// Chunk actions
if ( GetDefault < UEditorExperimentalSettings > ( ) - > bContextMenuChunkAssignments )
{
MenuBuilder . AddMenuEntry (
LOCTEXT ( " AssignAssetChunk " , " Assign to Chunk... " ) ,
LOCTEXT ( " AssignAssetChunkTooltip " , " Assign this asset to a specific Chunk " ) ,
FSlateIcon ( ) ,
FUIAction ( FExecuteAction : : CreateSP ( this , & FAssetContextMenu : : ExecuteAssignChunkID ) )
) ;
MenuBuilder . AddSubMenu (
LOCTEXT ( " RemoveAssetFromChunk " , " Remove from Chunk... " ) ,
LOCTEXT ( " RemoveAssetFromChunkTooltip " , " Removed an asset from a Chunk it's assigned to. " ) ,
FNewMenuDelegate : : CreateRaw ( this , & FAssetContextMenu : : MakeChunkIDListMenu )
) ;
MenuBuilder . AddMenuEntry (
LOCTEXT ( " RemoveAllChunkAssignments " , " Remove from all Chunks " ) ,
LOCTEXT ( " RemoveAllChunkAssignmentsTooltip " , " Removed an asset from all Chunks it's assigned to. " ) ,
FSlateIcon ( ) ,
FUIAction ( FExecuteAction : : CreateSP ( this , & FAssetContextMenu : : ExecuteRemoveAllChunkID ) )
) ;
}
}
MenuBuilder . EndSection ( ) ;
}
2015-01-16 15:39:47 -05:00
bool FAssetContextMenu : : CanExecuteAssetActions ( ) const
{
return ! bAtLeastOneClassSelected ;
}
2014-03-14 14:13:41 -04:00
bool FAssetContextMenu : : AddReferenceMenuOptions ( FMenuBuilder & MenuBuilder )
{
2015-04-23 17:05:53 -04:00
MenuBuilder . BeginSection ( " AssetContextReferences " , LOCTEXT ( " ReferencesMenuHeading " , " References " ) ) ;
2014-03-14 14:13:41 -04:00
{
MenuBuilder . AddMenuEntry (
LOCTEXT ( " CopyReference " , " Copy Reference " ) ,
LOCTEXT ( " CopyReferenceTooltip " , " Copies reference paths for the selected assets to the clipboard. " ) ,
FSlateIcon ( ) ,
FUIAction ( FExecuteAction : : CreateSP ( this , & FAssetContextMenu : : ExecuteCopyReference ) )
) ;
MenuBuilder . AddMenuEntry (
LOCTEXT ( " ReferenceViewer " , " Reference Viewer... " ) ,
LOCTEXT ( " ReferenceViewerTooltip " , " Shows a graph of references for this asset. " ) ,
FSlateIcon ( ) ,
FUIAction (
FExecuteAction : : CreateSP ( this , & FAssetContextMenu : : ExecuteShowReferenceViewer )
)
) ;
2015-04-22 15:58:21 -04:00
MenuBuilder . AddMenuEntry (
LOCTEXT ( " SizeMap " , " Size Map... " ) ,
LOCTEXT ( " SizeMapTooltip " , " Shows an interactive map of the approximate memory used by this asset and everything it references. " ) ,
FSlateIcon ( ) ,
FUIAction (
FExecuteAction : : CreateSP ( this , & FAssetContextMenu : : ExecuteShowSizeMap )
)
) ;
2014-03-14 14:13:41 -04:00
}
MenuBuilder . EndSection ( ) ;
return true ;
}
2014-07-30 17:50:36 -04:00
bool FAssetContextMenu : : AddDocumentationMenuOptions ( FMenuBuilder & MenuBuilder )
{
bool bAddedOption = false ;
// Objects must be loaded for this operation... for now
UClass * SelectedClass = ( SelectedAssets . Num ( ) > 0 ? SelectedAssets [ 0 ] . GetClass ( ) : nullptr ) ;
for ( const FAssetData & AssetData : SelectedAssets )
{
if ( SelectedClass ! = AssetData . GetClass ( ) )
{
SelectedClass = nullptr ;
break ;
}
}
// Go to C++ Code
if ( SelectedClass ! = nullptr )
{
// Blueprints are special. We won't link to C++ and for documentation we'll use the class it is generated from
const bool bIsBlueprint = SelectedClass - > IsChildOf < UBlueprint > ( ) ;
if ( bIsBlueprint )
{
FString * ParentClassPath = SelectedAssets [ 0 ] . TagsAndValues . Find ( GET_MEMBER_NAME_CHECKED ( UBlueprint , ParentClass ) ) ;
if ( ParentClassPath )
{
SelectedClass = FindObject < UClass > ( nullptr , * * ParentClassPath ) ;
}
}
if ( ! bIsBlueprint & & FSourceCodeNavigation : : IsCompilerAvailable ( ) )
{
FString ClassHeaderPath ;
if ( FSourceCodeNavigation : : FindClassHeaderPath ( SelectedClass , ClassHeaderPath ) & & IFileManager : : Get ( ) . FileSize ( * ClassHeaderPath ) ! = INDEX_NONE )
{
bAddedOption = true ;
const FString CodeFileName = FPaths : : GetCleanFilename ( * ClassHeaderPath ) ;
2014-10-09 12:35:10 -04:00
MenuBuilder . BeginSection ( " AssetCode " /*, LOCTEXT("AssetCodeHeading", "C++")*/ ) ;
2014-07-30 17:50:36 -04:00
{
MenuBuilder . AddMenuEntry (
2014-08-12 09:31:30 -04:00
FText : : Format ( LOCTEXT ( " GoToCodeForAsset " , " Open {0} " ) , FText : : FromString ( CodeFileName ) ) ,
FText : : Format ( LOCTEXT ( " GoToCodeForAsset_ToolTip " , " Opens the header file for this asset ({0}) in a code editing program " ) , FText : : FromString ( CodeFileName ) ) ,
2014-10-09 12:35:10 -04:00
FSlateIcon ( FEditorStyle : : GetStyleSetName ( ) , " ContentBrowser.AssetActions.GoToCodeForAsset " ) ,
2014-07-30 17:50:36 -04:00
FUIAction ( FExecuteAction : : CreateSP ( this , & FAssetContextMenu : : ExecuteGoToCodeForAsset , SelectedClass ) )
) ;
}
MenuBuilder . EndSection ( ) ;
}
}
const FString DocumentationLink = FEditorClassUtils : : GetDocumentationLink ( SelectedClass ) ;
2014-08-12 11:00:29 -04:00
if ( bIsBlueprint | | ! DocumentationLink . IsEmpty ( ) )
2014-07-30 17:50:36 -04:00
{
bAddedOption = true ;
2014-10-09 12:35:10 -04:00
MenuBuilder . BeginSection ( " AssetDocumentation " /*, LOCTEXT("AseetDocsHeading", "Documentation")*/ ) ;
2014-07-30 17:50:36 -04:00
{
2014-08-12 09:31:30 -04:00
if ( bIsBlueprint )
{
2014-08-12 11:00:29 -04:00
if ( ! DocumentationLink . IsEmpty ( ) )
{
MenuBuilder . AddMenuEntry (
FText : : Format ( LOCTEXT ( " GoToDocsForAssetWithClass " , " View Documentation - {0} " ) , SelectedClass - > GetDisplayNameText ( ) ) ,
FText : : Format ( LOCTEXT ( " GoToDocsForAssetWithClass_ToolTip " , " Click to open documentation for {0} " ) , SelectedClass - > GetDisplayNameText ( ) ) ,
FSlateIcon ( FEditorStyle : : GetStyleSetName ( ) , " HelpIcon.Hovered " ) ,
FUIAction ( FExecuteAction : : CreateSP ( this , & FAssetContextMenu : : ExecuteGoToDocsForAsset , SelectedClass ) )
) ;
}
2014-08-12 09:31:30 -04:00
2014-08-12 11:00:29 -04:00
UEnum * BlueprintTypeEnum = FindObject < UEnum > ( ANY_PACKAGE , TEXT ( " EBlueprintType " ) , true ) ;
2014-08-12 09:31:30 -04:00
FString * EnumString = SelectedAssets [ 0 ] . TagsAndValues . Find ( GET_MEMBER_NAME_CHECKED ( UBlueprint , BlueprintType ) ) ;
EBlueprintType BlueprintType = ( EnumString ? ( EBlueprintType ) BlueprintTypeEnum - > FindEnumIndex ( * * EnumString ) : BPTYPE_Normal ) ;
switch ( BlueprintType )
{
case BPTYPE_FunctionLibrary :
2014-08-12 11:00:29 -04:00
MenuBuilder . AddMenuEntry (
LOCTEXT ( " GoToDocsForMacroBlueprint " , " View Documentation - Function Library " ) ,
LOCTEXT ( " GoToDocsForMacroBlueprint_ToolTip " , " Click to open documentation on blueprint function libraries " ) ,
FSlateIcon ( FEditorStyle : : GetStyleSetName ( ) , " HelpIcon.Hovered " ) ,
FUIAction ( FExecuteAction : : CreateSP ( this , & FAssetContextMenu : : ExecuteGoToDocsForAsset , UBlueprint : : StaticClass ( ) , FString ( TEXT ( " UBlueprint_FunctionLibrary " ) ) ) )
) ;
2014-08-12 09:31:30 -04:00
break ;
case BPTYPE_Interface :
2014-08-12 11:00:29 -04:00
MenuBuilder . AddMenuEntry (
LOCTEXT ( " GoToDocsForInterfaceBlueprint " , " View Documentation - Interface " ) ,
LOCTEXT ( " GoToDocsForInterfaceBlueprint_ToolTip " , " Click to open documentation on blueprint interfaces " ) ,
FSlateIcon ( FEditorStyle : : GetStyleSetName ( ) , " HelpIcon.Hovered " ) ,
FUIAction ( FExecuteAction : : CreateSP ( this , & FAssetContextMenu : : ExecuteGoToDocsForAsset , UBlueprint : : StaticClass ( ) , FString ( TEXT ( " UBlueprint_Interface " ) ) ) )
) ;
2014-08-12 09:31:30 -04:00
break ;
case BPTYPE_MacroLibrary :
2014-08-12 11:00:29 -04:00
MenuBuilder . AddMenuEntry (
LOCTEXT ( " GoToDocsForInterfaceBlueprint " , " View Documentation - Macro " ) ,
LOCTEXT ( " GoToDocsForInterfaceBlueprint_ToolTip " , " Click to open documentation on blueprint macros " ) ,
FSlateIcon ( FEditorStyle : : GetStyleSetName ( ) , " HelpIcon.Hovered " ) ,
FUIAction ( FExecuteAction : : CreateSP ( this , & FAssetContextMenu : : ExecuteGoToDocsForAsset , UBlueprint : : StaticClass ( ) , FString ( TEXT ( " UBlueprint_Macro " ) ) ) )
) ;
2014-08-12 09:31:30 -04:00
break ;
default :
2014-08-12 11:00:29 -04:00
MenuBuilder . AddMenuEntry (
LOCTEXT ( " GoToDocsForBlueprint " , " View Documentation - Blueprint " ) ,
LOCTEXT ( " GoToDocsForBlueprint_ToolTip " , " Click to open documentation on blueprints " ) ,
FSlateIcon ( FEditorStyle : : GetStyleSetName ( ) , " HelpIcon.Hovered " ) ,
FUIAction ( FExecuteAction : : CreateSP ( this , & FAssetContextMenu : : ExecuteGoToDocsForAsset , UBlueprint : : StaticClass ( ) , FString ( TEXT ( " UBlueprint " ) ) ) )
) ;
2014-08-12 09:31:30 -04:00
}
}
else
{
MenuBuilder . AddMenuEntry (
LOCTEXT ( " GoToDocsForAsset " , " View Documentation " ) ,
LOCTEXT ( " GoToDocsForAsset_ToolTip " , " Click to open documentation " ) ,
FSlateIcon ( FEditorStyle : : GetStyleSetName ( ) , " HelpIcon.Hovered " ) ,
FUIAction ( FExecuteAction : : CreateSP ( this , & FAssetContextMenu : : ExecuteGoToDocsForAsset , SelectedClass ) )
) ;
}
2014-07-30 17:50:36 -04:00
}
MenuBuilder . EndSection ( ) ;
}
}
return bAddedOption ;
}
2014-03-14 14:13:41 -04:00
bool FAssetContextMenu : : AddAssetTypeMenuOptions ( FMenuBuilder & MenuBuilder )
{
bool bAnyTypeOptions = false ;
// Objects must be loaded for this operation... for now
TArray < FString > ObjectPaths ;
for ( int32 AssetIdx = 0 ; AssetIdx < SelectedAssets . Num ( ) ; + + AssetIdx )
{
ObjectPaths . Add ( SelectedAssets [ AssetIdx ] . ObjectPath . ToString ( ) ) ;
}
TArray < UObject * > SelectedObjects ;
if ( ContentBrowserUtils : : LoadAssetsIfNeeded ( ObjectPaths , SelectedObjects ) )
{
// Load the asset tools module
FAssetToolsModule & AssetToolsModule = FModuleManager : : LoadModuleChecked < FAssetToolsModule > ( TEXT ( " AssetTools " ) ) ;
bAnyTypeOptions = AssetToolsModule . Get ( ) . GetAssetActions ( SelectedObjects , MenuBuilder , /*bIncludeHeading=*/ true ) ;
}
return bAnyTypeOptions ;
}
bool FAssetContextMenu : : AddSourceControlMenuOptions ( FMenuBuilder & MenuBuilder )
{
2014-10-09 12:35:10 -04:00
MenuBuilder . AddMenuSeparator ( ) ;
2014-03-14 14:13:41 -04:00
if ( ISourceControlModule : : Get ( ) . IsEnabled ( ) )
{
2014-10-09 12:35:10 -04:00
// SCC sub menu
MenuBuilder . AddSubMenu (
LOCTEXT ( " SourceControlSubMenuLabel " , " Source Control " ) ,
LOCTEXT ( " SourceControlSubMenuToolTip " , " Source control actions. " ) ,
FNewMenuDelegate : : CreateSP ( this , & FAssetContextMenu : : FillSourceControlSubMenu ) ,
2015-01-16 15:39:47 -05:00
FUIAction (
FExecuteAction ( ) ,
FCanExecuteAction : : CreateSP ( this , & FAssetContextMenu : : CanExecuteSourceControlActions )
) ,
NAME_None ,
EUserInterfaceActionType : : Button ,
2014-10-09 12:35:10 -04:00
false ,
FSlateIcon ( FEditorStyle : : GetStyleSetName ( ) , " SourceControl.StatusIcon.On " )
) ;
}
else
{
MenuBuilder . AddMenuEntry (
LOCTEXT ( " SCCConnectToSourceControl " , " Connect To Source Control " ) ,
LOCTEXT ( " SCCConnectToSourceControlTooltip " , " Connect to source control to allow source control operations to be performed on content and levels. " ) ,
FSlateIcon ( FEditorStyle : : GetStyleSetName ( ) , " SourceControl.StatusIcon.Unknown " ) ,
FUIAction (
FExecuteAction : : CreateSP ( this , & FAssetContextMenu : : ExecuteEnableSourceControl ) ,
2015-01-16 15:39:47 -05:00
FCanExecuteAction : : CreateSP ( this , & FAssetContextMenu : : CanExecuteSourceControlActions )
2014-10-09 12:35:10 -04:00
)
2015-01-16 15:39:47 -05:00
) ;
2014-10-09 12:35:10 -04:00
}
// Diff selected
if ( CanExecuteDiffSelected ( ) )
{
MenuBuilder . AddMenuEntry (
LOCTEXT ( " DiffSelected " , " Diff Selected " ) ,
LOCTEXT ( " DiffSelectedTooltip " , " Diff the two assets that you have selected. " ) ,
FSlateIcon ( ) ,
FUIAction (
FExecuteAction : : CreateSP ( this , & FAssetContextMenu : : ExecuteDiffSelected )
)
) ;
}
return true ;
}
void FAssetContextMenu : : FillSourceControlSubMenu ( FMenuBuilder & MenuBuilder )
{
2014-10-28 22:59:51 -04:00
if ( CanExecuteSCCMerge ( ) )
{
MenuBuilder . AddMenuEntry (
LOCTEXT ( " SCCMerge " , " Merge " ) ,
LOCTEXT ( " SCCMergeTooltip " , " Opens the blueprint editor with the merge tool open. " ) ,
FSlateIcon ( ) ,
FUIAction (
FExecuteAction : : CreateSP ( this , & FAssetContextMenu : : ExecuteSCCMerge ) ,
FCanExecuteAction : : CreateSP ( this , & FAssetContextMenu : : CanExecuteSCCMerge )
)
) ;
}
2014-10-09 12:35:10 -04:00
if ( CanExecuteSCCSync ( ) )
2014-10-28 22:59:51 -04:00
{
MenuBuilder . AddMenuEntry (
LOCTEXT ( " SCCSync " , " Sync " ) ,
LOCTEXT ( " SCCSyncTooltip " , " Updates the item to the latest version in source control. " ) ,
FSlateIcon ( ) ,
FUIAction (
FExecuteAction : : CreateSP ( this , & FAssetContextMenu : : ExecuteSCCSync ) ,
FCanExecuteAction : : CreateSP ( this , & FAssetContextMenu : : CanExecuteSCCSync )
)
) ;
}
2014-03-14 14:13:41 -04:00
2014-10-28 22:59:51 -04:00
if ( CanExecuteSCCCheckOut ( ) )
{
MenuBuilder . AddMenuEntry (
LOCTEXT ( " SCCCheckOut " , " Check Out " ) ,
LOCTEXT ( " SCCCheckOutTooltip " , " Checks out the selected asset from source control. " ) ,
2015-04-20 00:01:25 -04:00
FSlateIcon ( ) ,
2014-10-28 22:59:51 -04:00
FUIAction (
FExecuteAction : : CreateSP ( this , & FAssetContextMenu : : ExecuteSCCCheckOut ) ,
FCanExecuteAction : : CreateSP ( this , & FAssetContextMenu : : CanExecuteSCCCheckOut )
)
) ;
}
2014-03-14 14:13:41 -04:00
2014-10-28 22:59:51 -04:00
if ( CanExecuteSCCOpenForAdd ( ) )
{
MenuBuilder . AddMenuEntry (
LOCTEXT ( " SCCOpenForAdd " , " Mark For Add " ) ,
LOCTEXT ( " SCCOpenForAddTooltip " , " Adds the selected asset to source control. " ) ,
2015-04-20 00:01:25 -04:00
FSlateIcon ( ) ,
2014-10-28 22:59:51 -04:00
FUIAction (
FExecuteAction : : CreateSP ( this , & FAssetContextMenu : : ExecuteSCCOpenForAdd ) ,
FCanExecuteAction : : CreateSP ( this , & FAssetContextMenu : : CanExecuteSCCOpenForAdd )
)
) ;
}
2014-03-14 14:13:41 -04:00
2014-10-28 22:59:51 -04:00
if ( CanExecuteSCCCheckIn ( ) )
{
MenuBuilder . AddMenuEntry (
LOCTEXT ( " SCCCheckIn " , " Check In " ) ,
LOCTEXT ( " SCCCheckInTooltip " , " Checks in the selected asset to source control. " ) ,
FSlateIcon ( ) ,
FUIAction (
FExecuteAction : : CreateSP ( this , & FAssetContextMenu : : ExecuteSCCCheckIn ) ,
FCanExecuteAction : : CreateSP ( this , & FAssetContextMenu : : CanExecuteSCCCheckIn )
)
) ;
}
MenuBuilder . AddMenuEntry (
LOCTEXT ( " SCCRefresh " , " Refresh " ) ,
LOCTEXT ( " SCCRefreshTooltip " , " Updates the source control status of the asset. " ) ,
2015-04-20 00:01:25 -04:00
FSlateIcon ( ) ,
2014-10-28 22:59:51 -04:00
FUIAction (
FExecuteAction : : CreateSP ( this , & FAssetContextMenu : : ExecuteSCCRefresh ) ,
FCanExecuteAction : : CreateSP ( this , & FAssetContextMenu : : CanExecuteSCCRefresh )
)
) ;
if ( CanExecuteSCCHistory ( ) )
{
MenuBuilder . AddMenuEntry (
LOCTEXT ( " SCCHistory " , " History " ) ,
LOCTEXT ( " SCCHistoryTooltip " , " Displays the source control revision history of the selected asset. " ) ,
FSlateIcon ( ) ,
FUIAction (
FExecuteAction : : CreateSP ( this , & FAssetContextMenu : : ExecuteSCCHistory ) ,
FCanExecuteAction : : CreateSP ( this , & FAssetContextMenu : : CanExecuteSCCHistory )
)
) ;
2014-03-14 14:13:41 -04:00
MenuBuilder . AddMenuEntry (
2014-10-28 22:59:51 -04:00
LOCTEXT ( " SCCDiffAgainstDepot " , " Diff Against Depot " ) ,
LOCTEXT ( " SCCDiffAgainstDepotTooltip " , " Look at differences between your version of the asset and that in source control. " ) ,
FSlateIcon ( ) ,
2014-03-14 14:13:41 -04:00
FUIAction (
2014-10-28 22:59:51 -04:00
FExecuteAction : : CreateSP ( this , & FAssetContextMenu : : ExecuteSCCDiffAgainstDepot ) ,
FCanExecuteAction : : CreateSP ( this , & FAssetContextMenu : : CanExecuteSCCDiffAgainstDepot )
)
) ;
}
2014-03-14 14:13:41 -04:00
2014-10-28 22:59:51 -04:00
if ( CanExecuteSCCRevert ( ) )
{
MenuBuilder . AddMenuEntry (
LOCTEXT ( " SCCRevert " , " Revert " ) ,
LOCTEXT ( " SCCRevertTooltip " , " Reverts the asset to the state it was before it was checked out. " ) ,
FSlateIcon ( ) ,
FUIAction (
FExecuteAction : : CreateSP ( this , & FAssetContextMenu : : ExecuteSCCRevert ) ,
FCanExecuteAction : : CreateSP ( this , & FAssetContextMenu : : CanExecuteSCCRevert )
)
) ;
}
2014-03-14 14:13:41 -04:00
}
2015-01-16 15:39:47 -05:00
bool FAssetContextMenu : : CanExecuteSourceControlActions ( ) const
{
return ! bAtLeastOneClassSelected ;
}
2014-03-14 14:13:41 -04:00
bool FAssetContextMenu : : AddCollectionMenuOptions ( FMenuBuilder & MenuBuilder )
{
// "Remove from collection" (only display option if exactly one collection is selected)
if ( SourcesData . Collections . Num ( ) = = 1 )
{
MenuBuilder . BeginSection ( " AssetContextCollections " , LOCTEXT ( " AssetCollectionOptionsMenuHeading " , " Collections " ) ) ;
{
MenuBuilder . AddMenuEntry (
LOCTEXT ( " RemoveFromCollection " , " Remove From Collection " ) ,
LOCTEXT ( " RemoveFromCollection_ToolTip " , " Removes the selected asset from the current collection. " ) ,
FSlateIcon ( ) ,
FUIAction (
FExecuteAction : : CreateSP ( this , & FAssetContextMenu : : ExecuteRemoveFromCollection ) ,
FCanExecuteAction : : CreateSP ( this , & FAssetContextMenu : : CanExecuteRemoveFromCollection )
)
) ;
}
MenuBuilder . EndSection ( ) ;
return true ;
}
return false ;
}
2014-10-09 12:35:10 -04:00
bool FAssetContextMenu : : AreImportedAssetActionsVisible ( ) const
{
FAssetToolsModule & AssetToolsModule = FModuleManager : : Get ( ) . LoadModuleChecked < FAssetToolsModule > ( " AssetTools " ) ;
// Check that all of the selected assets are imported
for ( auto & SelectedAsset : SelectedAssets )
{
auto AssetClass = SelectedAsset . GetClass ( ) ;
if ( AssetClass )
{
auto AssetTypeActions = AssetToolsModule . Get ( ) . GetAssetTypeActionsForClass ( AssetClass ) . Pin ( ) ;
if ( ! AssetTypeActions . IsValid ( ) | | ! AssetTypeActions - > IsImportedAsset ( ) )
{
return false ;
}
}
}
return true ;
}
bool FAssetContextMenu : : CanExecuteImportedAssetActions ( const TArray < FString > ResolvedFilePaths ) const
{
// Verify that all the file paths are legitimate
for ( const auto & SourceFilePath : ResolvedFilePaths )
{
if ( ! SourceFilePath . Len ( ) | | IFileManager : : Get ( ) . FileSize ( * SourceFilePath ) = = INDEX_NONE )
{
return false ;
}
}
return true ;
}
void FAssetContextMenu : : ExecuteReimport ( )
{
// Reimport all selected assets
for ( auto & SelectedAsset : SelectedAssets )
{
const auto Asset = SelectedAsset . GetAsset ( ) ;
if ( Asset )
{
FReimportManager : : Instance ( ) - > Reimport ( Asset , /*bAskForNewFileIfMissing=*/ true ) ;
}
}
}
void FAssetContextMenu : : ExecuteFindSourceInExplorer ( const TArray < FString > ResolvedFilePaths )
{
// Open all files in the explorer
for ( const auto & SourceFilePath : ResolvedFilePaths )
{
FPlatformProcess : : ExploreFolder ( * FPaths : : GetPath ( SourceFilePath ) ) ;
}
}
void FAssetContextMenu : : ExecuteOpenInExternalEditor ( const TArray < FString > ResolvedFilePaths )
{
// Open all files in their respective editor
for ( const auto & SourceFilePath : ResolvedFilePaths )
{
FPlatformProcess : : LaunchFileInDefaultExternalApplication ( * SourceFilePath , NULL , ELaunchVerb : : Edit ) ;
}
}
void FAssetContextMenu : : GetSelectedAssetsByClass ( TMap < UClass * , TArray < UObject * > > & OutSelectedAssetsByClass ) const
{
// Sort all selected assets by class
for ( const auto & SelectedAsset : SelectedAssets )
{
auto Asset = SelectedAsset . GetAsset ( ) ;
auto AssetClass = Asset - > GetClass ( ) ;
if ( ! OutSelectedAssetsByClass . Contains ( AssetClass ) )
{
OutSelectedAssetsByClass . Add ( AssetClass ) ;
}
OutSelectedAssetsByClass [ AssetClass ] . Add ( Asset ) ;
}
}
void FAssetContextMenu : : GetSelectedAssetSourceFilePaths ( TArray < FString > & OutFilePaths ) const
{
OutFilePaths . Empty ( ) ;
TMap < UClass * , TArray < UObject * > > SelectedAssetsByClass ;
GetSelectedAssetsByClass ( SelectedAssetsByClass ) ;
FAssetToolsModule & AssetToolsModule = FModuleManager : : Get ( ) . LoadModuleChecked < FAssetToolsModule > ( " AssetTools " ) ;
// Get the source file paths for the assets of each type
for ( const auto & AssetsByClassPair : SelectedAssetsByClass )
{
const auto AssetTypeActions = AssetToolsModule . Get ( ) . GetAssetTypeActionsForClass ( AssetsByClassPair . Key ) ;
if ( AssetTypeActions . IsValid ( ) )
{
const auto & TypeAssets = AssetsByClassPair . Value ;
TArray < FString > AssetSourcePaths ;
AssetTypeActions . Pin ( ) - > GetResolvedSourceFilePaths ( TypeAssets , AssetSourcePaths ) ;
OutFilePaths . Append ( AssetSourcePaths ) ;
}
}
}
2014-03-14 14:13:41 -04:00
void FAssetContextMenu : : ExecuteSyncToAssetTree ( )
{
OnFindInAssetTreeRequested . ExecuteIfBound ( SelectedAssets ) ;
}
void FAssetContextMenu : : ExecuteFindInExplorer ( )
{
for ( int32 AssetIdx = 0 ; AssetIdx < SelectedAssets . Num ( ) ; + + AssetIdx )
{
const UObject * Asset = SelectedAssets [ AssetIdx ] . GetAsset ( ) ;
if ( Asset )
{
FAssetData AssetData ( Asset ) ;
2014-04-23 19:06:37 -04:00
const bool bIsWorldAsset = ( AssetData . AssetClass = = UWorld : : StaticClass ( ) - > GetFName ( ) ) ;
const FString Extension = bIsWorldAsset ? FPackageName : : GetMapPackageExtension ( ) : FPackageName : : GetAssetPackageExtension ( ) ;
const FString FilePath = FPackageName : : LongPackageNameToFilename ( AssetData . PackageName . ToString ( ) , Extension ) ;
2014-03-14 14:13:41 -04:00
const FString FullFilePath = FPaths : : ConvertRelativePathToFull ( FilePath ) ;
2014-04-23 19:06:37 -04:00
FPlatformProcess : : ExploreFolder ( * FullFilePath ) ;
2014-03-14 14:13:41 -04:00
}
}
}
void FAssetContextMenu : : ExecuteCreateBlueprintUsing ( )
{
if ( SelectedAssets . Num ( ) = = 1 )
{
UObject * Asset = SelectedAssets [ 0 ] . GetAsset ( ) ;
FKismetEditorUtilities : : CreateBlueprintUsingAsset ( Asset , true ) ;
}
}
void FAssetContextMenu : : GetSelectedAssets ( TArray < UObject * > & Assets , bool SkipRedirectors )
{
for ( int32 AssetIdx = 0 ; AssetIdx < SelectedAssets . Num ( ) ; + + AssetIdx )
{
if ( SkipRedirectors & & ( SelectedAssets [ AssetIdx ] . AssetClass = = UObjectRedirector : : StaticClass ( ) - > GetFName ( ) ) )
{
// Don't operate on Redirectors
continue ;
}
UObject * Object = SelectedAssets [ AssetIdx ] . GetAsset ( ) ;
if ( Object )
{
Assets . Add ( Object ) ;
}
}
}
/** Generates a reference graph of the world and can then find actors referencing specified objects */
struct WorldReferenceGenerator : public FFindReferencedAssets
{
void BuildReferencingData ( )
{
MarkAllObjects ( ) ;
const int32 MaxRecursionDepth = 0 ;
const bool bIncludeClasses = true ;
const bool bIncludeDefaults = false ;
const bool bReverseReferenceGraph = true ;
2014-04-23 19:58:21 -04:00
UWorld * World = GWorld ;
// Generate the reference graph for the world
FReferencedAssets * WorldReferencer = new ( Referencers ) FReferencedAssets ( World ) ;
FFindAssetsArchive ( World , WorldReferencer - > AssetList , & ReferenceGraph , MaxRecursionDepth , bIncludeClasses , bIncludeDefaults , bReverseReferenceGraph ) ;
2014-03-15 01:14:25 -04:00
// Also include all the streaming levels in the results
2014-04-23 19:58:21 -04:00
for ( int32 LevelIndex = 0 ; LevelIndex < World - > StreamingLevels . Num ( ) ; + + LevelIndex )
2014-03-15 01:14:25 -04:00
{
2014-04-23 19:58:21 -04:00
ULevelStreaming * StreamingLevel = World - > StreamingLevels [ LevelIndex ] ;
2014-03-15 01:14:25 -04:00
if ( StreamingLevel ! = NULL )
{
ULevel * Level = StreamingLevel - > GetLoadedLevel ( ) ;
if ( Level ! = NULL )
{
// Generate the reference graph for each streamed in level
FReferencedAssets * LevelReferencer = new ( Referencers ) FReferencedAssets ( Level ) ;
FFindAssetsArchive ( Level , LevelReferencer - > AssetList , & ReferenceGraph , MaxRecursionDepth , bIncludeClasses , bIncludeDefaults , bReverseReferenceGraph ) ;
}
}
}
2014-03-14 14:13:41 -04:00
}
void MarkAllObjects ( )
{
// Mark all objects so we don't get into an endless recursion
for ( FObjectIterator It ; It ; + + It )
{
It - > Mark ( OBJECTMARK_TagExp ) ;
}
}
void Generate ( const UObject * AssetToFind , TArray < TWeakObjectPtr < UObject > > & OutObjects )
{
// Don't examine visited objects
if ( ! AssetToFind - > HasAnyMarks ( OBJECTMARK_TagExp ) )
{
return ;
}
AssetToFind - > UnMark ( OBJECTMARK_TagExp ) ;
// Return once we find a parent object that is an actor
if ( AssetToFind - > IsA ( AActor : : StaticClass ( ) ) )
{
OutObjects . Add ( AssetToFind ) ;
return ;
}
// Transverse the reference graph looking for actor objects
TSet < UObject * > * Referencers = ReferenceGraph . Find ( AssetToFind ) ;
if ( Referencers )
{
for ( TSet < UObject * > : : TConstIterator SetIt ( * Referencers ) ; SetIt ; + + SetIt )
{
Generate ( * SetIt , OutObjects ) ;
}
}
}
} ;
void FAssetContextMenu : : ExecuteFindAssetInWorld ( )
{
TArray < UObject * > AssetsToFind ;
const bool SkipRedirectors = true ;
GetSelectedAssets ( AssetsToFind , SkipRedirectors ) ;
const bool NoteSelectionChange = true ;
const bool DeselectBSPSurfs = true ;
const bool WarnAboutManyActors = false ;
GEditor - > SelectNone ( NoteSelectionChange , DeselectBSPSurfs , WarnAboutManyActors ) ;
if ( AssetsToFind . Num ( ) > 0 )
{
2014-10-08 04:42:34 -04:00
FScopedSlowTask SlowTask ( 2 + AssetsToFind . Num ( ) , NSLOCTEXT ( " AssetContextMenu " , " FindAssetInWorld " , " Finding actors that use this asset... " ) ) ;
SlowTask . MakeDialog ( ) ;
2014-03-14 14:13:41 -04:00
CollectGarbage ( GARBAGE_COLLECTION_KEEPFLAGS ) ;
TArray < TWeakObjectPtr < UObject > > OutObjects ;
WorldReferenceGenerator ObjRefGenerator ;
2014-10-08 04:42:34 -04:00
SlowTask . EnterProgressFrame ( ) ;
2014-03-14 14:13:41 -04:00
ObjRefGenerator . BuildReferencingData ( ) ;
for ( int32 AssetIdx = 0 ; AssetIdx < AssetsToFind . Num ( ) ; + + AssetIdx )
{
2014-10-08 04:42:34 -04:00
SlowTask . EnterProgressFrame ( ) ;
2014-03-14 14:13:41 -04:00
ObjRefGenerator . MarkAllObjects ( ) ;
ObjRefGenerator . Generate ( AssetsToFind [ AssetIdx ] , OutObjects ) ;
}
2014-10-08 04:42:34 -04:00
SlowTask . EnterProgressFrame ( ) ;
2014-03-14 14:13:41 -04:00
if ( OutObjects . Num ( ) > 0 )
{
const bool InSelected = true ;
const bool Notify = false ;
// Select referencing actors
for ( int32 ActorIdx = 0 ; ActorIdx < OutObjects . Num ( ) ; + + ActorIdx )
{
GEditor - > SelectActor ( CastChecked < AActor > ( OutObjects [ ActorIdx ] . Get ( ) ) , InSelected , Notify ) ;
}
GEditor - > NoteSelectionChange ( ) ;
}
else
{
FNotificationInfo Info ( LOCTEXT ( " NoReferencingActorsFound " , " No actors found. " ) ) ;
Info . ExpireDuration = 3.0f ;
FSlateNotificationManager : : Get ( ) . AddNotification ( Info ) ;
}
}
}
void FAssetContextMenu : : ExecutePropertyMatrix ( )
{
TArray < UObject * > ObjectsForPropertiesMenu ;
const bool SkipRedirectors = true ;
GetSelectedAssets ( ObjectsForPropertiesMenu , SkipRedirectors ) ;
if ( ObjectsForPropertiesMenu . Num ( ) > 0 )
{
FPropertyEditorModule & PropertyEditorModule = FModuleManager : : LoadModuleChecked < FPropertyEditorModule > ( " PropertyEditor " ) ;
PropertyEditorModule . CreatePropertyEditorToolkit ( EToolkitMode : : Standalone , TSharedPtr < IToolkitHost > ( ) , ObjectsForPropertiesMenu ) ;
}
}
2014-10-09 12:35:10 -04:00
void FAssetContextMenu : : ExecuteEditAsset ( )
{
TMap < UClass * , TArray < UObject * > > SelectedAssetsByClass ;
GetSelectedAssetsByClass ( SelectedAssetsByClass ) ;
// Open
for ( const auto & AssetsByClassPair : SelectedAssetsByClass )
{
const auto & TypeAssets = AssetsByClassPair . Value ;
FAssetEditorManager : : Get ( ) . OpenEditorForAssets ( TypeAssets ) ;
}
}
2014-03-14 14:13:41 -04:00
void FAssetContextMenu : : ExecuteSaveAsset ( )
{
TArray < UPackage * > PackagesToSave ;
GetSelectedPackages ( PackagesToSave ) ;
TArray < UPackage * > PackagesWithExternalRefs ;
FString PackageNames ;
if ( PackageTools : : CheckForReferencesToExternalPackages ( & PackagesToSave , & PackagesWithExternalRefs ) )
{
for ( int32 PkgIdx = 0 ; PkgIdx < PackagesWithExternalRefs . Num ( ) ; + + PkgIdx )
{
PackageNames + = FString : : Printf ( TEXT ( " %s \n " ) , * PackagesWithExternalRefs [ PkgIdx ] - > GetName ( ) ) ;
}
bool bProceed = EAppReturnType : : Yes = = FMessageDialog : : Open ( EAppMsgType : : YesNo , FText : : Format ( NSLOCTEXT ( " UnrealEd " , " Warning_ExternalPackageRef " , " The following assets have references to external assets: \n {0} \n External assets won't be found when in a game and all references will be broken. Proceed? " ) , FText : : FromString ( PackageNames ) ) ) ;
if ( ! bProceed )
{
return ;
}
}
const bool bCheckDirty = false ;
const bool bPromptToSave = false ;
const FEditorFileUtils : : EPromptReturnCode Return = FEditorFileUtils : : PromptForCheckoutAndSave ( PackagesToSave , bCheckDirty , bPromptToSave ) ;
//return Return == FEditorFileUtils::EPromptReturnCode::PR_Success;
}
void FAssetContextMenu : : ExecuteDiffSelected ( ) const
{
if ( SelectedAssets . Num ( ) > = 2 )
{
UObject * FirstObjectSelected = SelectedAssets [ 0 ] . GetAsset ( ) ;
UObject * SecondObjectSelected = SelectedAssets [ 1 ] . GetAsset ( ) ;
if ( ( FirstObjectSelected ! = NULL ) & & ( SecondObjectSelected ! = NULL ) )
{
// Load the asset registry module
FAssetToolsModule & AssetToolsModule = FModuleManager : : GetModuleChecked < FAssetToolsModule > ( " AssetTools " ) ;
FRevisionInfo CurrentRevision ;
2015-01-20 05:48:14 -05:00
CurrentRevision . Revision = TEXT ( " " ) ;
2014-03-14 14:13:41 -04:00
AssetToolsModule . Get ( ) . DiffAssets ( FirstObjectSelected , SecondObjectSelected , CurrentRevision , CurrentRevision ) ;
}
}
}
void FAssetContextMenu : : ExecuteDuplicate ( )
{
TArray < UObject * > ObjectsToDuplicate ;
const bool SkipRedirectors = true ;
GetSelectedAssets ( ObjectsToDuplicate , SkipRedirectors ) ;
if ( ObjectsToDuplicate . Num ( ) = = 1 )
{
OnDuplicateRequested . ExecuteIfBound ( ObjectsToDuplicate [ 0 ] ) ;
}
else if ( ObjectsToDuplicate . Num ( ) > 1 )
{
TArray < UObject * > NewObjects ;
ObjectTools : : DuplicateObjects ( ObjectsToDuplicate , TEXT ( " " ) , TEXT ( " " ) , /*bOpenDialog=*/ false , & NewObjects ) ;
TArray < FAssetData > AssetsToSync ;
for ( auto ObjIt = NewObjects . CreateConstIterator ( ) ; ObjIt ; + + ObjIt )
{
new ( AssetsToSync ) FAssetData ( * ObjIt ) ;
}
// Sync to asset tree
if ( NewObjects . Num ( ) > 0 )
{
OnFindInAssetTreeRequested . ExecuteIfBound ( AssetsToSync ) ;
}
}
}
2014-08-01 05:51:26 -04:00
void FAssetContextMenu : : ExecuteRename ( )
2014-03-14 14:13:41 -04:00
{
TArray < FAssetData > AssetViewSelectedAssets = AssetView . Pin ( ) - > GetSelectedAssets ( ) ;
TArray < FString > SelectedFolders = AssetView . Pin ( ) - > GetSelectedFolders ( ) ;
if ( AssetViewSelectedAssets . Num ( ) = = 1 & & SelectedFolders . Num ( ) = = 0 )
{
// Don't operate on Redirectors
if ( AssetViewSelectedAssets [ 0 ] . AssetClass ! = UObjectRedirector : : StaticClass ( ) - > GetFName ( ) )
{
OnRenameRequested . ExecuteIfBound ( AssetViewSelectedAssets [ 0 ] ) ;
}
}
if ( AssetViewSelectedAssets . Num ( ) = = 0 & & SelectedFolders . Num ( ) = = 1 )
{
OnRenameFolderRequested . ExecuteIfBound ( SelectedFolders [ 0 ] ) ;
}
}
2014-08-01 05:51:26 -04:00
void FAssetContextMenu : : ExecuteDelete ( )
2014-03-14 14:13:41 -04:00
{
TArray < FAssetData > AssetViewSelectedAssets = AssetView . Pin ( ) - > GetSelectedAssets ( ) ;
if ( AssetViewSelectedAssets . Num ( ) > 0 )
{
TArray < FAssetData > AssetsToDelete ;
for ( auto AssetIt = AssetViewSelectedAssets . CreateConstIterator ( ) ; AssetIt ; + + AssetIt )
{
const FAssetData & AssetData = * AssetIt ;
if ( AssetData . AssetClass = = UObjectRedirector : : StaticClass ( ) - > GetFName ( ) )
{
// Don't operate on Redirectors
continue ;
}
AssetsToDelete . Add ( AssetData ) ;
}
if ( AssetsToDelete . Num ( ) > 0 )
{
ObjectTools : : DeleteAssets ( AssetsToDelete ) ;
}
}
TArray < FString > SelectedFolders = AssetView . Pin ( ) - > GetSelectedFolders ( ) ;
if ( SelectedFolders . Num ( ) > 0 )
{
FText Prompt ;
if ( SelectedFolders . Num ( ) = = 1 )
{
Prompt = FText : : Format ( LOCTEXT ( " FolderDeleteConfirm_Single " , " Delete folder '{0}'? " ) , FText : : FromString ( SelectedFolders [ 0 ] ) ) ;
}
else
{
Prompt = FText : : Format ( LOCTEXT ( " FolderDeleteConfirm_Multiple " , " Delete {0} folders? " ) , FText : : AsNumber ( SelectedFolders . Num ( ) ) ) ;
}
// Spawn a confirmation dialog since this is potentially a highly destructive operation
ContentBrowserUtils : : DisplayConfirmationPopup (
Prompt ,
LOCTEXT ( " FolderDeleteConfirm_Yes " , " Delete " ) ,
LOCTEXT ( " FolderDeleteConfirm_No " , " Cancel " ) ,
AssetView . Pin ( ) . ToSharedRef ( ) ,
FOnClicked : : CreateSP ( this , & FAssetContextMenu : : ExecuteDeleteFolderConfirmed ) ) ;
}
}
FReply FAssetContextMenu : : ExecuteDeleteFolderConfirmed ( )
{
TArray < FString > SelectedFolders = AssetView . Pin ( ) - > GetSelectedFolders ( ) ;
if ( SelectedFolders . Num ( ) > 0 )
{
ContentBrowserUtils : : DeleteFolders ( SelectedFolders ) ;
}
return FReply : : Handled ( ) ;
}
void FAssetContextMenu : : ExecuteConsolidate ( )
{
TArray < UObject * > ObjectsToConsolidate ;
const bool SkipRedirectors = true ;
GetSelectedAssets ( ObjectsToConsolidate , SkipRedirectors ) ;
if ( ObjectsToConsolidate . Num ( ) > 0 )
{
FConsolidateToolWindow : : AddConsolidationObjects ( ObjectsToConsolidate ) ;
}
}
void FAssetContextMenu : : ExecuteCaptureThumbnail ( )
{
FViewport * Viewport = GEditor - > GetActiveViewport ( ) ;
if ( ensure ( GCurrentLevelEditingViewportClient ) & & ensure ( Viewport ) )
{
//have to re-render the requested viewport
FLevelEditorViewportClient * OldViewportClient = GCurrentLevelEditingViewportClient ;
//remove selection box around client during render
GCurrentLevelEditingViewportClient = NULL ;
Viewport - > Draw ( ) ;
ContentBrowserUtils : : CaptureThumbnailFromViewport ( Viewport , SelectedAssets ) ;
//redraw viewport to have the yellow highlight again
GCurrentLevelEditingViewportClient = OldViewportClient ;
Viewport - > Draw ( ) ;
}
}
void FAssetContextMenu : : ExecuteClearThumbnail ( )
{
ContentBrowserUtils : : ClearCustomThumbnails ( SelectedAssets ) ;
}
void FAssetContextMenu : : ExecuteMigrateAsset ( )
{
// Get a list of package names for input into MigratePackages
TArray < FName > PackageNames ;
for ( int32 AssetIdx = 0 ; AssetIdx < SelectedAssets . Num ( ) ; + + AssetIdx )
{
PackageNames . Add ( SelectedAssets [ AssetIdx ] . PackageName ) ;
}
FAssetToolsModule & AssetToolsModule = FModuleManager : : Get ( ) . LoadModuleChecked < FAssetToolsModule > ( " AssetTools " ) ;
AssetToolsModule . Get ( ) . MigratePackages ( PackageNames ) ;
}
void FAssetContextMenu : : ExecuteShowReferenceViewer ( )
{
TArray < FName > PackageNames ;
for ( auto AssetIt = SelectedAssets . CreateConstIterator ( ) ; AssetIt ; + + AssetIt )
{
PackageNames . Add ( AssetIt - > PackageName ) ;
}
if ( PackageNames . Num ( ) > 0 )
{
IReferenceViewerModule : : Get ( ) . InvokeReferenceViewerTab ( PackageNames ) ;
}
}
2015-04-22 15:58:21 -04:00
void FAssetContextMenu : : ExecuteShowSizeMap ( )
{
TArray < FName > PackageNames ;
for ( auto AssetIt = SelectedAssets . CreateConstIterator ( ) ; AssetIt ; + + AssetIt )
{
PackageNames . Add ( AssetIt - > PackageName ) ;
}
if ( PackageNames . Num ( ) > 0 )
{
ISizeMapModule : : Get ( ) . InvokeSizeMapTab ( PackageNames ) ;
}
}
2014-07-30 17:50:36 -04:00
void FAssetContextMenu : : ExecuteGoToCodeForAsset ( UClass * SelectedClass )
{
if ( SelectedClass )
{
FString ClassHeaderPath ;
if ( FSourceCodeNavigation : : FindClassHeaderPath ( SelectedClass , ClassHeaderPath ) & & IFileManager : : Get ( ) . FileSize ( * ClassHeaderPath ) ! = INDEX_NONE )
{
const FString AbsoluteHeaderPath = IFileManager : : Get ( ) . ConvertToAbsolutePathForExternalAppForRead ( * ClassHeaderPath ) ;
FSourceCodeNavigation : : OpenSourceFile ( AbsoluteHeaderPath ) ;
}
}
}
void FAssetContextMenu : : ExecuteGoToDocsForAsset ( UClass * SelectedClass )
2014-08-12 09:31:30 -04:00
{
ExecuteGoToDocsForAsset ( SelectedClass , FString ( ) ) ;
}
void FAssetContextMenu : : ExecuteGoToDocsForAsset ( UClass * SelectedClass , const FString ExcerptSection )
2014-07-30 17:50:36 -04:00
{
if ( SelectedClass )
{
2014-08-12 09:31:30 -04:00
FString DocumentationLink = FEditorClassUtils : : GetDocumentationLink ( SelectedClass , ExcerptSection ) ;
2014-07-30 17:50:36 -04:00
if ( ! DocumentationLink . IsEmpty ( ) )
{
2015-01-14 13:15:22 -05:00
IDocumentation : : Get ( ) - > Open ( DocumentationLink , FDocumentationSourceInfo ( TEXT ( " cb_docs " ) ) ) ;
2014-07-30 17:50:36 -04:00
}
}
}
2014-03-14 14:13:41 -04:00
void FAssetContextMenu : : ExecuteCopyReference ( )
{
ContentBrowserUtils : : CopyAssetReferencesToClipboard ( SelectedAssets ) ;
}
void FAssetContextMenu : : ExecuteExport ( )
{
TArray < UObject * > ObjectsToExport ;
const bool SkipRedirectors = false ;
GetSelectedAssets ( ObjectsToExport , SkipRedirectors ) ;
if ( ObjectsToExport . Num ( ) > 0 )
{
ObjectTools : : ExportObjects ( ObjectsToExport , /*bPromptForEachFileName=*/ true ) ;
}
}
void FAssetContextMenu : : ExecuteBulkExport ( )
{
TArray < UObject * > ObjectsToExport ;
const bool SkipRedirectors = false ;
GetSelectedAssets ( ObjectsToExport , SkipRedirectors ) ;
if ( ObjectsToExport . Num ( ) > 0 )
{
ObjectTools : : ExportObjects ( ObjectsToExport , /*bPromptForEachFileName=*/ false ) ;
}
}
void FAssetContextMenu : : ExecuteRemoveFromCollection ( )
{
if ( ensure ( SourcesData . Collections . Num ( ) = = 1 ) )
{
TArray < FName > AssetsToRemove ;
for ( auto AssetIt = SelectedAssets . CreateConstIterator ( ) ; AssetIt ; + + AssetIt )
{
AssetsToRemove . Add ( ( * AssetIt ) . ObjectPath ) ;
}
if ( AssetsToRemove . Num ( ) > 0 )
{
FCollectionManagerModule & CollectionManagerModule = FModuleManager : : LoadModuleChecked < FCollectionManagerModule > ( " CollectionManager " ) ;
FName CollectionName = SourcesData . Collections [ 0 ] . Name ;
ECollectionShareType : : Type CollectionType = SourcesData . Collections [ 0 ] . Type ;
CollectionManagerModule . Get ( ) . RemoveFromCollection ( CollectionName , CollectionType , AssetsToRemove ) ;
OnAssetViewRefreshRequested . ExecuteIfBound ( ) ;
}
}
}
void FAssetContextMenu : : ExecuteSCCRefresh ( )
{
TArray < FString > PackageNames ;
GetSelectedPackageNames ( PackageNames ) ;
ISourceControlModule : : Get ( ) . GetProvider ( ) . Execute ( ISourceControlOperation : : Create < FUpdateStatus > ( ) , SourceControlHelpers : : PackageFilenames ( PackageNames ) , EConcurrency : : Asynchronous ) ;
}
2014-10-28 22:59:51 -04:00
void FAssetContextMenu : : ExecuteSCCMerge ( )
{
FAssetToolsModule & AssetToolsModule = FModuleManager : : GetModuleChecked < FAssetToolsModule > ( " AssetTools " ) ;
for ( int32 AssetIdx = 0 ; AssetIdx < SelectedAssets . Num ( ) ; AssetIdx + + )
{
// Get the actual asset (will load it)
const FAssetData & AssetData = SelectedAssets [ AssetIdx ] ;
UObject * CurrentObject = AssetData . GetAsset ( ) ;
if ( CurrentObject )
{
const FString PackagePath = AssetData . PackageName . ToString ( ) ;
const FString PackageName = AssetData . AssetName . ToString ( ) ;
auto AssetTypeActions = AssetToolsModule . Get ( ) . GetAssetTypeActionsForClass ( CurrentObject - > GetClass ( ) ) . Pin ( ) ;
if ( AssetTypeActions . IsValid ( ) )
{
AssetTypeActions - > Merge ( CurrentObject ) ;
}
}
}
}
2014-03-14 14:13:41 -04:00
void FAssetContextMenu : : ExecuteSCCCheckOut ( )
{
TArray < UPackage * > PackagesToCheckOut ;
GetSelectedPackages ( PackagesToCheckOut ) ;
if ( PackagesToCheckOut . Num ( ) > 0 )
{
// Update the source control status of all potentially relevant packages
ISourceControlModule : : Get ( ) . GetProvider ( ) . Execute ( ISourceControlOperation : : Create < FUpdateStatus > ( ) , PackagesToCheckOut ) ;
// Now check them out
FEditorFileUtils : : CheckoutPackages ( PackagesToCheckOut ) ;
}
}
void FAssetContextMenu : : ExecuteSCCOpenForAdd ( )
{
TArray < FString > PackageNames ;
GetSelectedPackageNames ( PackageNames ) ;
ISourceControlProvider & SourceControlProvider = ISourceControlModule : : Get ( ) . GetProvider ( ) ;
TArray < FString > PackagesToAdd ;
TArray < UPackage * > PackagesToSave ;
for ( auto PackageIt = PackageNames . CreateConstIterator ( ) ; PackageIt ; + + PackageIt )
{
FSourceControlStatePtr SourceControlState = SourceControlProvider . GetState ( SourceControlHelpers : : PackageFilename ( * PackageIt ) , EStateCacheUsage : : Use ) ;
if ( SourceControlState . IsValid ( ) & & ! SourceControlState - > IsSourceControlled ( ) )
{
PackagesToAdd . Add ( * PackageIt ) ;
// Make sure the file actually exists on disk before adding it
FString Filename ;
if ( ! FPackageName : : DoesPackageExist ( * PackageIt , NULL , & Filename ) )
{
UPackage * Package = FindPackage ( NULL , * * PackageIt ) ;
if ( Package )
{
PackagesToSave . Add ( Package ) ;
}
}
}
}
if ( PackagesToAdd . Num ( ) > 0 )
{
// If any of the packages are new, save them now
if ( PackagesToSave . Num ( ) > 0 )
{
const bool bCheckDirty = false ;
const bool bPromptToSave = false ;
TArray < UPackage * > FailedPackages ;
const FEditorFileUtils : : EPromptReturnCode Return = FEditorFileUtils : : PromptForCheckoutAndSave ( PackagesToSave , bCheckDirty , bPromptToSave , & FailedPackages ) ;
if ( FailedPackages . Num ( ) > 0 )
{
// don't try and add files that failed to save - remove them from the list
for ( auto FailedPackageIt = FailedPackages . CreateConstIterator ( ) ; FailedPackageIt ; FailedPackageIt + + )
{
PackagesToAdd . Remove ( ( * FailedPackageIt ) - > GetName ( ) ) ;
}
}
}
SourceControlProvider . Execute ( ISourceControlOperation : : Create < FMarkForAdd > ( ) , SourceControlHelpers : : PackageFilenames ( PackagesToAdd ) ) ;
}
}
void FAssetContextMenu : : ExecuteSCCCheckIn ( )
{
TArray < UPackage * > Packages ;
GetSelectedPackages ( Packages ) ;
// Prompt the user to ask if they would like to first save any dirty packages they are trying to check-in
const FEditorFileUtils : : EPromptReturnCode UserResponse = FEditorFileUtils : : PromptForCheckoutAndSave ( Packages , true , true ) ;
// If the user elected to save dirty packages, but one or more of the packages failed to save properly OR if the user
// canceled out of the prompt, don't follow through on the check-in process
const bool bShouldProceed = ( UserResponse = = FEditorFileUtils : : EPromptReturnCode : : PR_Success | | UserResponse = = FEditorFileUtils : : EPromptReturnCode : : PR_Declined ) ;
if ( bShouldProceed )
{
2015-02-16 05:11:32 -05:00
TArray < FString > PackageNames ;
GetSelectedPackageNames ( PackageNames ) ;
const bool bUseSourceControlStateCache = true ;
FSourceControlWindows : : PromptForCheckin ( bUseSourceControlStateCache , PackageNames ) ;
2014-03-14 14:13:41 -04:00
}
else
{
// If a failure occurred, alert the user that the check-in was aborted. This warning shouldn't be necessary if the user cancelled
// from the dialog, because they obviously intended to cancel the whole operation.
if ( UserResponse = = FEditorFileUtils : : EPromptReturnCode : : PR_Failure )
{
FMessageDialog : : Open ( EAppMsgType : : Ok , NSLOCTEXT ( " UnrealEd " , " SCC_Checkin_Aborted " , " Check-in aborted as a result of save failure. " ) ) ;
}
}
}
void FAssetContextMenu : : ExecuteSCCHistory ( )
{
TArray < FString > PackageNames ;
GetSelectedPackageNames ( PackageNames ) ;
FSourceControlWindows : : DisplayRevisionHistory ( SourceControlHelpers : : PackageFilenames ( PackageNames ) ) ;
}
void FAssetContextMenu : : ExecuteSCCDiffAgainstDepot ( ) const
{
// Load the asset registry module
FAssetToolsModule & AssetToolsModule = FModuleManager : : GetModuleChecked < FAssetToolsModule > ( " AssetTools " ) ;
// Iterate over each selected asset
for ( int32 AssetIdx = 0 ; AssetIdx < SelectedAssets . Num ( ) ; AssetIdx + + )
{
// Get the actual asset (will load it)
const FAssetData & AssetData = SelectedAssets [ AssetIdx ] ;
UObject * CurrentObject = AssetData . GetAsset ( ) ;
if ( CurrentObject )
{
const FString PackagePath = AssetData . PackageName . ToString ( ) ;
const FString PackageName = AssetData . AssetName . ToString ( ) ;
AssetToolsModule . Get ( ) . DiffAgainstDepot ( CurrentObject , PackagePath , PackageName ) ;
}
}
}
void FAssetContextMenu : : ExecuteSCCRevert ( )
{
TArray < FString > PackageNames ;
GetSelectedPackageNames ( PackageNames ) ;
FSourceControlWindows : : PromptForRevert ( PackageNames ) ;
}
void FAssetContextMenu : : ExecuteSCCSync ( )
{
TArray < FString > PackageNames ;
GetSelectedPackageNames ( PackageNames ) ;
TArray < FString > PackageFileNames = SourceControlHelpers : : PackageFilenames ( PackageNames ) ;
TArray < UPackage * > Packages ;
GetSelectedPackages ( Packages ) ;
2014-04-23 18:51:56 -04:00
FText ErrorMessage ;
PackageTools : : UnloadPackages ( Packages , ErrorMessage ) ;
if ( ! ErrorMessage . IsEmpty ( ) )
{
FMessageDialog : : Open ( EAppMsgType : : Ok , ErrorMessage ) ;
}
else
2014-03-14 14:13:41 -04:00
{
ISourceControlModule : : Get ( ) . GetProvider ( ) . Execute ( ISourceControlOperation : : Create < FSync > ( ) , PackageFileNames ) ;
for ( TArray < FString > : : TConstIterator PackageIter ( PackageNames ) ; PackageIter ; + + PackageIter )
{
PackageTools : : LoadPackage ( * PackageIter ) ;
}
2015-01-06 04:15:02 -05:00
ExecuteSCCRefresh ( ) ;
2014-03-14 14:13:41 -04:00
}
}
void FAssetContextMenu : : ExecuteEnableSourceControl ( )
{
ISourceControlModule : : Get ( ) . ShowLoginDialog ( FSourceControlLoginClosed ( ) , ELoginWindowMode : : Modeless ) ;
}
bool FAssetContextMenu : : CanExecuteSyncToAssetTree ( ) const
{
return SelectedAssets . Num ( ) > 0 ;
}
bool FAssetContextMenu : : CanExecuteFindInExplorer ( ) const
{
return SelectedAssets . Num ( ) > 0 ;
}
bool FAssetContextMenu : : CanExecuteCreateBlueprintUsing ( ) const
{
// Only work if you have a single asset selected
if ( SelectedAssets . Num ( ) = = 1 )
{
UObject * Asset = SelectedAssets [ 0 ] . GetAsset ( ) ;
// See if we know how to make a component from this asset
TArray < TSubclassOf < UActorComponent > > ComponentClassList = FComponentAssetBrokerage : : GetComponentsForAsset ( Asset ) ;
return ( ComponentClassList . Num ( ) > 0 ) ;
}
return false ;
}
bool FAssetContextMenu : : CanExecuteFindAssetInWorld ( ) const
{
return bAtLeastOneNonRedirectorSelected ;
}
bool FAssetContextMenu : : CanExecuteProperties ( ) const
{
return bAtLeastOneNonRedirectorSelected ;
}
bool FAssetContextMenu : : CanExecutePropertyMatrix ( ) const
{
return bAtLeastOneNonRedirectorSelected ;
}
bool FAssetContextMenu : : CanExecuteDuplicate ( ) const
{
2015-03-20 15:04:00 -04:00
const TArray < FAssetData > AssetViewSelectedAssets = AssetView . Pin ( ) - > GetSelectedAssets ( ) ;
uint32 NumNonRedirectors = 0 ;
for ( auto & AssetData : AssetViewSelectedAssets )
{
if ( ! AssetData . IsValid ( ) )
{
continue ;
}
if ( AssetData . AssetClass = = NAME_Class )
{
return false ;
}
if ( AssetData . AssetClass ! = UObjectRedirector : : StaticClass ( ) - > GetFName ( ) )
{
+ + NumNonRedirectors ;
}
}
return ( NumNonRedirectors > 0 ) ;
2014-03-14 14:13:41 -04:00
}
bool FAssetContextMenu : : CanExecuteRename ( ) const
{
TArray < FAssetData > AssetViewSelectedAssets = AssetView . Pin ( ) - > GetSelectedAssets ( ) ;
TArray < FString > SelectedFolders = AssetView . Pin ( ) - > GetSelectedFolders ( ) ;
2015-01-16 15:39:47 -05:00
const bool bOneAssetSelected = AssetViewSelectedAssets . Num ( ) = = 1 & & SelectedFolders . Num ( ) = = 0 // A single asset
& & AssetViewSelectedAssets [ 0 ] . AssetClass ! = UObjectRedirector : : StaticClass ( ) - > GetFName ( ) // Which isn't a redirector
& & AssetViewSelectedAssets [ 0 ] . AssetClass ! = NAME_Class ; // And isn't a class
const bool bOneFolderSelected = AssetViewSelectedAssets . Num ( ) = = 0 & & SelectedFolders . Num ( ) = = 1 // A single folder
& & ! ContentBrowserUtils : : IsClassPath ( SelectedFolders [ 0 ] ) ; // Which doesn't belong to a class path
2014-03-14 14:13:41 -04:00
return ( bOneAssetSelected | | bOneFolderSelected ) & & ! AssetView . Pin ( ) - > IsThumbnailEditMode ( ) ;
}
bool FAssetContextMenu : : CanExecuteDelete ( ) const
{
TArray < FAssetData > AssetViewSelectedAssets = AssetView . Pin ( ) - > GetSelectedAssets ( ) ;
TArray < FString > SelectedFolders = AssetView . Pin ( ) - > GetSelectedFolders ( ) ;
2015-01-16 15:39:47 -05:00
int32 NumAssetItems , NumClassItems ;
ContentBrowserUtils : : CountItemTypes ( AssetViewSelectedAssets , NumAssetItems , NumClassItems ) ;
int32 NumAssetPaths , NumClassPaths ;
ContentBrowserUtils : : CountPathTypes ( SelectedFolders , NumAssetPaths , NumClassPaths ) ;
// We can't delete classes, or folders containing classes
return ( NumAssetItems > 0 & & NumClassItems = = 0 ) | | ( NumAssetPaths > 0 & & NumClassPaths = = 0 ) ;
2014-03-14 14:13:41 -04:00
}
bool FAssetContextMenu : : CanExecuteRemoveFromCollection ( ) const
{
return SourcesData . Collections . Num ( ) = = 1 ;
}
bool FAssetContextMenu : : CanExecuteSCCRefresh ( ) const
{
return ISourceControlModule : : Get ( ) . IsEnabled ( ) ;
}
2014-10-28 22:59:51 -04:00
bool FAssetContextMenu : : CanExecuteSCCMerge ( ) const
{
FAssetToolsModule & AssetToolsModule = FModuleManager : : GetModuleChecked < FAssetToolsModule > ( " AssetTools " ) ;
2014-12-18 13:57:42 -05:00
bool bCanExecuteMerge = bCanExecuteSCCMerge ;
for ( int32 AssetIdx = 0 ; AssetIdx < SelectedAssets . Num ( ) & & bCanExecuteMerge ; AssetIdx + + )
2014-10-28 22:59:51 -04:00
{
2014-12-18 13:57:42 -05:00
// Get the actual asset (will load it)
const FAssetData & AssetData = SelectedAssets [ AssetIdx ] ;
UObject * CurrentObject = AssetData . GetAsset ( ) ;
if ( CurrentObject )
2014-10-28 22:59:51 -04:00
{
2014-12-18 13:57:42 -05:00
auto AssetTypeActions = AssetToolsModule . Get ( ) . GetAssetTypeActionsForClass ( CurrentObject - > GetClass ( ) ) . Pin ( ) ;
if ( AssetTypeActions . IsValid ( ) )
2014-10-28 22:59:51 -04:00
{
2014-12-18 13:57:42 -05:00
bCanExecuteMerge = AssetTypeActions - > CanMerge ( ) ;
2014-10-28 22:59:51 -04:00
}
}
2014-12-18 13:57:42 -05:00
else
{
bCanExecuteMerge = false ;
}
2014-10-28 22:59:51 -04:00
}
2014-12-18 13:57:42 -05:00
2014-10-28 22:59:51 -04:00
return bCanExecuteMerge ;
}
2014-03-14 14:13:41 -04:00
bool FAssetContextMenu : : CanExecuteSCCCheckOut ( ) const
{
return bCanExecuteSCCCheckOut ;
}
bool FAssetContextMenu : : CanExecuteSCCOpenForAdd ( ) const
{
return bCanExecuteSCCOpenForAdd ;
}
bool FAssetContextMenu : : CanExecuteSCCCheckIn ( ) const
{
return bCanExecuteSCCCheckIn ;
}
bool FAssetContextMenu : : CanExecuteSCCHistory ( ) const
{
return bCanExecuteSCCHistory ;
}
bool FAssetContextMenu : : CanExecuteSCCDiffAgainstDepot ( ) const
{
return bCanExecuteSCCHistory ;
}
bool FAssetContextMenu : : CanExecuteSCCRevert ( ) const
{
return bCanExecuteSCCRevert ;
}
bool FAssetContextMenu : : CanExecuteSCCSync ( ) const
{
return bCanExecuteSCCSync ;
}
bool FAssetContextMenu : : CanExecuteConsolidate ( ) const
{
TArray < UObject * > ProposedObjects ;
for ( int32 AssetIdx = 0 ; AssetIdx < SelectedAssets . Num ( ) ; + + AssetIdx )
{
// Don't load assets here. Only operate on already loaded assets.
if ( SelectedAssets [ AssetIdx ] . IsAssetLoaded ( ) )
{
UObject * Object = SelectedAssets [ AssetIdx ] . GetAsset ( ) ;
if ( Object )
{
ProposedObjects . Add ( Object ) ;
}
}
}
if ( ProposedObjects . Num ( ) > 0 )
{
TArray < UObject * > CompatibleObjects ;
return FConsolidateToolWindow : : DetermineAssetCompatibility ( ProposedObjects , CompatibleObjects ) ;
}
return false ;
}
bool FAssetContextMenu : : CanExecuteSaveAsset ( ) const
{
2015-01-16 15:39:47 -05:00
if ( bAtLeastOneClassSelected )
{
return false ;
}
2014-03-14 14:13:41 -04:00
TArray < UPackage * > Packages ;
GetSelectedPackages ( Packages ) ;
// only enabled if at least one selected package is loaded at all
for ( int32 PackageIdx = 0 ; PackageIdx < Packages . Num ( ) ; + + PackageIdx )
{
if ( Packages [ PackageIdx ] ! = NULL )
{
return true ;
}
}
return false ;
}
bool FAssetContextMenu : : CanExecuteDiffSelected ( ) const
{
bool bCanDiffSelected = false ;
2015-01-16 15:39:47 -05:00
if ( SelectedAssets . Num ( ) = = 2 & & ! bAtLeastOneClassSelected )
2014-03-14 14:13:41 -04:00
{
FAssetData const & FirstSelection = SelectedAssets [ 0 ] ;
FAssetData const & SecondSelection = SelectedAssets [ 1 ] ;
if ( FirstSelection . AssetClass ! = SecondSelection . AssetClass )
{
bCanDiffSelected = false ;
}
else
{
bCanDiffSelected = ( FirstSelection . AssetClass = = UBlueprint : : StaticClass ( ) - > GetFName ( ) ) ;
}
}
return bCanDiffSelected ;
}
bool FAssetContextMenu : : CanExecuteCaptureThumbnail ( ) const
{
return GCurrentLevelEditingViewportClient ! = NULL ;
}
bool FAssetContextMenu : : CanClearCustomThumbnails ( ) const
{
for ( auto AssetIt = SelectedAssets . CreateConstIterator ( ) ; AssetIt ; + + AssetIt )
{
if ( ContentBrowserUtils : : AssetHasCustomThumbnail ( * AssetIt ) )
{
return true ;
}
}
return false ;
}
void FAssetContextMenu : : CacheCanExecuteVars ( )
{
bAtLeastOneNonRedirectorSelected = false ;
2015-01-16 15:39:47 -05:00
bAtLeastOneClassSelected = false ;
2014-10-28 22:59:51 -04:00
bCanExecuteSCCMerge = false ;
2014-03-14 14:13:41 -04:00
bCanExecuteSCCCheckOut = false ;
bCanExecuteSCCOpenForAdd = false ;
bCanExecuteSCCCheckIn = false ;
bCanExecuteSCCHistory = false ;
bCanExecuteSCCRevert = false ;
bCanExecuteSCCSync = false ;
for ( auto AssetIt = SelectedAssets . CreateConstIterator ( ) ; AssetIt ; + + AssetIt )
{
const FAssetData & AssetData = * AssetIt ;
if ( ! AssetData . IsValid ( ) )
{
continue ;
}
if ( ! bAtLeastOneNonRedirectorSelected & & AssetData . AssetClass ! = UObjectRedirector : : StaticClass ( ) - > GetFName ( ) )
{
bAtLeastOneNonRedirectorSelected = true ;
}
2015-01-16 15:39:47 -05:00
bAtLeastOneClassSelected | = AssetData . AssetClass = = NAME_Class ;
2014-03-14 14:13:41 -04:00
ISourceControlProvider & SourceControlProvider = ISourceControlModule : : Get ( ) . GetProvider ( ) ;
if ( ISourceControlModule : : Get ( ) . IsEnabled ( ) )
{
// Check the SCC state for each package in the selected paths
FSourceControlStatePtr SourceControlState = SourceControlProvider . GetState ( SourceControlHelpers : : PackageFilename ( AssetData . PackageName . ToString ( ) ) , EStateCacheUsage : : Use ) ;
if ( SourceControlState . IsValid ( ) )
{
2014-10-28 22:59:51 -04:00
if ( SourceControlState - > IsConflicted ( ) )
{
bCanExecuteSCCMerge = true ;
}
2014-03-14 14:13:41 -04:00
if ( SourceControlState - > CanCheckout ( ) )
{
bCanExecuteSCCCheckOut = true ;
}
2014-04-23 18:13:09 -04:00
if ( ! SourceControlState - > IsSourceControlled ( ) & & SourceControlState - > CanAdd ( ) )
2014-03-14 14:13:41 -04:00
{
bCanExecuteSCCOpenForAdd = true ;
}
2014-04-23 18:13:09 -04:00
else if ( SourceControlState - > IsSourceControlled ( ) & & ! SourceControlState - > IsAdded ( ) )
2014-03-14 14:13:41 -04:00
{
bCanExecuteSCCHistory = true ;
}
if ( ! SourceControlState - > IsCurrent ( ) )
{
bCanExecuteSCCSync = true ;
}
2014-06-05 12:10:47 -04:00
if ( SourceControlState - > CanCheckIn ( ) )
2014-03-14 14:13:41 -04:00
{
bCanExecuteSCCCheckIn = true ;
bCanExecuteSCCRevert = true ;
}
}
}
if ( bAtLeastOneNonRedirectorSelected
2015-01-16 15:39:47 -05:00
& & bAtLeastOneClassSelected
2014-10-28 22:59:51 -04:00
& & bCanExecuteSCCMerge
2014-03-14 14:13:41 -04:00
& & bCanExecuteSCCCheckOut
& & bCanExecuteSCCOpenForAdd
& & bCanExecuteSCCCheckIn
& & bCanExecuteSCCHistory
& & bCanExecuteSCCRevert
& & bCanExecuteSCCSync
)
{
// All options are available, no need to keep iterating
break ;
}
}
}
void FAssetContextMenu : : GetSelectedPackageNames ( TArray < FString > & OutPackageNames ) const
{
for ( int32 AssetIdx = 0 ; AssetIdx < SelectedAssets . Num ( ) ; + + AssetIdx )
{
OutPackageNames . Add ( SelectedAssets [ AssetIdx ] . PackageName . ToString ( ) ) ;
}
}
void FAssetContextMenu : : GetSelectedPackages ( TArray < UPackage * > & OutPackages ) const
{
for ( int32 AssetIdx = 0 ; AssetIdx < SelectedAssets . Num ( ) ; + + AssetIdx )
{
UPackage * Package = FindPackage ( NULL , * SelectedAssets [ AssetIdx ] . PackageName . ToString ( ) ) ;
if ( Package )
{
OutPackages . Add ( Package ) ;
}
}
}
2014-08-07 17:34:29 -04:00
void FAssetContextMenu : : MakeChunkIDListMenu ( FMenuBuilder & MenuBuilder )
{
TArray < int32 > FoundChunks ;
TArray < FAssetData > AssetViewSelectedAssets = AssetView . Pin ( ) - > GetSelectedAssets ( ) ;
for ( const auto & SelectedAsset : AssetViewSelectedAssets )
{
UPackage * Package = FindPackage ( NULL , * SelectedAsset . PackageName . ToString ( ) ) ;
if ( Package )
{
for ( auto ChunkID : Package - > GetChunkIDs ( ) )
{
FoundChunks . AddUnique ( ChunkID ) ;
}
}
}
for ( auto ChunkID : FoundChunks )
{
MenuBuilder . AddMenuEntry (
FText : : Format ( LOCTEXT ( " PackageChunk " , " Chunk {0} " ) , FText : : AsNumber ( ChunkID ) ) ,
FText ( ) ,
FSlateIcon ( ) ,
FUIAction (
FExecuteAction : : CreateSP ( this , & FAssetContextMenu : : ExecuteRemoveChunkID , ChunkID )
)
) ;
}
}
void FAssetContextMenu : : ExecuteAssignChunkID ( )
{
TArray < FAssetData > AssetViewSelectedAssets = AssetView . Pin ( ) - > GetSelectedAssets ( ) ;
auto AssetViewPtr = AssetView . Pin ( ) ;
if ( AssetViewSelectedAssets . Num ( ) > 0 & & AssetViewPtr . IsValid ( ) )
{
// Determine the position of the window so that it will spawn near the mouse, but not go off the screen.
const FVector2D CursorPos = FSlateApplication : : Get ( ) . GetCursorPos ( ) ;
FSlateRect Anchor ( CursorPos . X , CursorPos . Y , CursorPos . X , CursorPos . Y ) ;
FVector2D AdjustedSummonLocation = FSlateApplication : : Get ( ) . CalculatePopupWindowPosition ( Anchor , SColorPicker : : DEFAULT_WINDOW_SIZE , Orient_Horizontal ) ;
TSharedPtr < SWindow > Window = SNew ( SWindow )
. AutoCenter ( EAutoCenter : : None )
. ScreenPosition ( AdjustedSummonLocation )
. SupportsMaximize ( false )
. SupportsMinimize ( false )
. SizingRule ( ESizingRule : : Autosized )
. Title ( LOCTEXT ( " WindowHeader " , " Enter Chunk ID " ) ) ;
Window - > SetContent (
SNew ( SVerticalBox )
+ SVerticalBox : : Slot ( )
. FillHeight ( 1.0f )
. HAlign ( HAlign_Fill )
. VAlign ( VAlign_Top )
[
SNew ( SHorizontalBox )
+ SHorizontalBox : : Slot ( )
. FillWidth ( 1.0f )
. HAlign ( HAlign_Left )
. VAlign ( VAlign_Center )
[
SNew ( STextBlock )
. Text ( LOCTEXT ( " MeshPaint_LabelStrength " , " Chunk ID " ) )
]
+ SHorizontalBox : : Slot ( )
. FillWidth ( 2.0f )
. HAlign ( HAlign_Fill )
. VAlign ( VAlign_Center )
[
SNew ( SNumericEntryBox < int32 > )
. AllowSpin ( true )
. MinSliderValue ( 0 )
. MaxSliderValue ( 300 )
. MinValue ( 0 )
. MaxValue ( 300 )
. Value ( this , & FAssetContextMenu : : GetChunkIDSelection )
. OnValueChanged ( this , & FAssetContextMenu : : OnChunkIDAssignChanged )
]
]
+ SVerticalBox : : Slot ( )
. FillHeight ( 1.0f )
. HAlign ( HAlign_Fill )
. VAlign ( VAlign_Bottom )
[
SNew ( SHorizontalBox )
+ SHorizontalBox : : Slot ( )
. FillWidth ( 1.0f )
. HAlign ( HAlign_Right )
. VAlign ( VAlign_Center )
[
SNew ( SButton )
. Text ( LOCTEXT ( " ChunkIDAssign_Yes " , " OK " ) )
. OnClicked ( this , & FAssetContextMenu : : OnChunkIDAssignCommit , Window )
]
+ SHorizontalBox : : Slot ( )
. FillWidth ( 1.0f )
. HAlign ( HAlign_Left )
. VAlign ( VAlign_Center )
[
SNew ( SButton )
. Text ( LOCTEXT ( " ChunkIDAssign_No " , " Cancel " ) )
. OnClicked ( this , & FAssetContextMenu : : OnChunkIDAssignCancel , Window )
]
]
) ;
ChunkIDSelected = 0 ;
FSlateApplication : : Get ( ) . AddModalWindow ( Window . ToSharedRef ( ) , AssetViewPtr ) ;
}
}
void FAssetContextMenu : : ExecuteRemoveAllChunkID ( )
{
TArray < int32 > EmptyChunks ;
TArray < FAssetData > AssetViewSelectedAssets = AssetView . Pin ( ) - > GetSelectedAssets ( ) ;
for ( const auto & SelectedAsset : AssetViewSelectedAssets )
{
UPackage * Package = FindPackage ( NULL , * SelectedAsset . PackageName . ToString ( ) ) ;
if ( Package )
{
Package - > SetChunkIDs ( EmptyChunks ) ;
Package - > SetDirtyFlag ( true ) ;
}
}
}
TOptional < int32 > FAssetContextMenu : : GetChunkIDSelection ( ) const
{
return ChunkIDSelected ;
}
void FAssetContextMenu : : OnChunkIDAssignChanged ( int32 NewChunkID )
{
ChunkIDSelected = NewChunkID ;
}
FReply FAssetContextMenu : : OnChunkIDAssignCommit ( TSharedPtr < SWindow > Window )
{
TArray < FAssetData > AssetViewSelectedAssets = AssetView . Pin ( ) - > GetSelectedAssets ( ) ;
for ( const auto & SelectedAsset : AssetViewSelectedAssets )
{
UPackage * Package = FindPackage ( NULL , * SelectedAsset . PackageName . ToString ( ) ) ;
if ( Package )
{
TArray < int32 > CurrentChunks = Package - > GetChunkIDs ( ) ;
CurrentChunks . AddUnique ( ChunkIDSelected ) ;
Package - > SetChunkIDs ( CurrentChunks ) ;
Package - > SetDirtyFlag ( true ) ;
}
}
Window - > RequestDestroyWindow ( ) ;
return FReply : : Handled ( ) ;
}
FReply FAssetContextMenu : : OnChunkIDAssignCancel ( TSharedPtr < SWindow > Window )
{
Window - > RequestDestroyWindow ( ) ;
return FReply : : Handled ( ) ;
}
void FAssetContextMenu : : ExecuteRemoveChunkID ( int32 ChunkID )
{
TArray < FAssetData > AssetViewSelectedAssets = AssetView . Pin ( ) - > GetSelectedAssets ( ) ;
for ( const auto & SelectedAsset : AssetViewSelectedAssets )
{
UPackage * Package = FindPackage ( NULL , * SelectedAsset . PackageName . ToString ( ) ) ;
if ( Package )
{
int32 FoundIndex ;
TArray < int32 > CurrentChunks = Package - > GetChunkIDs ( ) ;
CurrentChunks . Find ( ChunkID , FoundIndex ) ;
if ( FoundIndex ! = INDEX_NONE )
{
CurrentChunks . RemoveAt ( FoundIndex ) ;
Package - > SetChunkIDs ( CurrentChunks ) ;
Package - > SetDirtyFlag ( true ) ;
}
}
}
}
2014-03-14 14:13:41 -04:00
# undef LOCTEXT_NAMESPACE