You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
#rb Rex.Hill, Jason.Stasik #rnx #ROBOMERGE-OWNER: jamie.dale #ROBOMERGE-AUTHOR: jamie.dale #ROBOMERGE-SOURCE: CL 20627582 via CL 20627615 via CL 20627698 via CL 20627704 #ROBOMERGE-BOT: UE5 (Release-Engine-Staging -> Main) (v955-20579017) [CL 20636216 by jamie dale in ue5-main branch]
1164 lines
37 KiB
C++
1164 lines
37 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "AssetContextMenu.h"
|
|
#include "AssetRegistry/AssetData.h"
|
|
|
|
#include "ToolMenus.h"
|
|
#include "ContentBrowserMenuContexts.h"
|
|
#include "ContentBrowserDataSource.h"
|
|
|
|
#include "IAssetTools.h"
|
|
#include "AssetToolsModule.h"
|
|
#include "ContentBrowserUtils.h"
|
|
#include "SAssetView.h"
|
|
#include "ContentBrowserModule.h"
|
|
#include "ContentBrowserSingleton.h"
|
|
#include "Styling/AppStyle.h"
|
|
#include "HAL/FileManager.h"
|
|
|
|
#include "ICollectionManager.h"
|
|
#include "CollectionManagerModule.h"
|
|
#include "CollectionAssetManagement.h"
|
|
|
|
#include "Toolkits/GlobalEditorCommonCommands.h"
|
|
#include "Framework/Commands/GenericCommands.h"
|
|
#include "ContentBrowserCommands.h"
|
|
#include "Misc/PathViews.h"
|
|
|
|
|
|
namespace ContentBrowserConsoleVariables
|
|
{
|
|
static bool ContentBrowser_EnablePublicAssetFeature = false;
|
|
static FAutoConsoleVariableRef ContentBrowser_EnablePublicAssetFeatureCVar(TEXT("ContentBrowser.PublicAsset.EnablePublicAssetFeature"),
|
|
ContentBrowser_EnablePublicAssetFeature, TEXT("Enables the Experimental Public Asset Feature (False: disabled, True:enabled"));
|
|
}
|
|
#define LOCTEXT_NAMESPACE "ContentBrowser"
|
|
|
|
FAssetContextMenu::FAssetContextMenu(const TWeakPtr<SAssetView>& InAssetView)
|
|
: AssetView(InAssetView)
|
|
{
|
|
}
|
|
|
|
void FAssetContextMenu::BindCommands(TSharedPtr< FUICommandList >& Commands)
|
|
{
|
|
Commands->MapAction(FGenericCommands::Get().Duplicate, FUIAction(
|
|
FExecuteAction::CreateSP(this, &FAssetContextMenu::ExecuteDuplicate),
|
|
FCanExecuteAction::CreateSP(this, &FAssetContextMenu::CanExecuteDuplicate)
|
|
));
|
|
|
|
Commands->MapAction(FGlobalEditorCommonCommands::Get().FindInContentBrowser, FUIAction(
|
|
FExecuteAction::CreateSP(this, &FAssetContextMenu::ExecuteSyncToAssetTree),
|
|
FCanExecuteAction::CreateSP(this, &FAssetContextMenu::CanExecuteSyncToAssetTree)
|
|
));
|
|
}
|
|
|
|
TSharedRef<SWidget> FAssetContextMenu::MakeContextMenu(TArrayView<const FContentBrowserItem> InSelectedItems, const FSourcesData& InSourcesData, TSharedPtr< FUICommandList > InCommandList)
|
|
{
|
|
SetSelectedItems(InSelectedItems);
|
|
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();
|
|
|
|
TSharedPtr<FExtender> MenuExtender;
|
|
{
|
|
TArray<FAssetData> SelectedAssets;
|
|
for (const FContentBrowserItem& SelectedFile : SelectedFiles)
|
|
{
|
|
FAssetData ItemAssetData;
|
|
if (SelectedFile.Legacy_TryGetAssetData(ItemAssetData))
|
|
{
|
|
SelectedAssets.Add(ItemAssetData);
|
|
}
|
|
}
|
|
|
|
if (SelectedAssets.Num() > 0)
|
|
{
|
|
TArray<TSharedPtr<FExtender>> Extenders;
|
|
for (int32 i = 0; i < MenuExtenderDelegates.Num(); ++i)
|
|
{
|
|
if (MenuExtenderDelegates[i].IsBound())
|
|
{
|
|
Extenders.Add(MenuExtenderDelegates[i].Execute(SelectedAssets));
|
|
}
|
|
}
|
|
MenuExtender = FExtender::Combine(Extenders);
|
|
}
|
|
}
|
|
|
|
UContentBrowserAssetContextMenuContext* ContextObject = NewObject<UContentBrowserAssetContextMenuContext>();
|
|
ContextObject->AssetContextMenu = SharedThis(this);
|
|
|
|
UToolMenus* ToolMenus = UToolMenus::Get();
|
|
|
|
static const FName BaseMenuName("ContentBrowser.AssetContextMenu");
|
|
static const FName ItemContextMenuName("ContentBrowser.ItemContextMenu");
|
|
RegisterContextMenu(BaseMenuName);
|
|
|
|
TArray<UObject*> SelectedObjects;
|
|
|
|
// Create menu hierarchy based on class hierarchy
|
|
FName MenuName = BaseMenuName;
|
|
{
|
|
// TODO: Ideally all of this asset specific stuff would happen in the asset data source, however we
|
|
// need to keep it here for now to build the correct menu name and register the correct extenders
|
|
|
|
// Objects must be loaded for this operation... for now
|
|
TArray<FString> ObjectPaths;
|
|
UContentBrowserDataSource* CommonDataSource = nullptr;
|
|
bool bKeepCheckingCommonDataSource = true;
|
|
for (const FContentBrowserItem& SelectedItem : SelectedItems)
|
|
{
|
|
if (bKeepCheckingCommonDataSource)
|
|
{
|
|
if (const FContentBrowserItemData* PrimaryInternalItem = SelectedItem.GetPrimaryInternalItem())
|
|
{
|
|
if (UContentBrowserDataSource* OwnerDataSource = PrimaryInternalItem->GetOwnerDataSource())
|
|
{
|
|
if (CommonDataSource == nullptr)
|
|
{
|
|
CommonDataSource = OwnerDataSource;
|
|
}
|
|
else if (CommonDataSource != OwnerDataSource)
|
|
{
|
|
CommonDataSource = nullptr;
|
|
bKeepCheckingCommonDataSource = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
FAssetData ItemAssetData;
|
|
if (SelectedItem.Legacy_TryGetAssetData(ItemAssetData))
|
|
{
|
|
ObjectPaths.Add(ItemAssetData.ObjectPath.ToString());
|
|
}
|
|
}
|
|
|
|
FAssetToolsModule& AssetToolsModule = FModuleManager::LoadModuleChecked<FAssetToolsModule>("AssetTools");
|
|
const TSharedRef<FPathPermissionList>& WritableFolderFilter = AssetToolsModule.Get().GetWritableFolderPermissionList();
|
|
|
|
ContextObject->bCanBeModified = ObjectPaths.Num() == 0;
|
|
|
|
ContextObject->SelectedObjects.Reset();
|
|
if (ContentBrowserUtils::LoadAssetsIfNeeded(ObjectPaths, SelectedObjects) && SelectedObjects.Num() > 0)
|
|
{
|
|
ContextObject->SelectedObjects.Append(SelectedObjects);
|
|
|
|
// Find common class for selected objects
|
|
UClass* CommonClass = SelectedObjects[0]->GetClass();
|
|
for (int32 ObjIdx = 1; ObjIdx < SelectedObjects.Num(); ++ObjIdx)
|
|
{
|
|
while (!SelectedObjects[ObjIdx]->IsA(CommonClass))
|
|
{
|
|
CommonClass = CommonClass->GetSuperClass();
|
|
}
|
|
}
|
|
ContextObject->CommonClass = CommonClass;
|
|
|
|
ContextObject->bCanBeModified = true;
|
|
for (const UObject* SelectedObject : SelectedObjects)
|
|
{
|
|
if (SelectedObject)
|
|
{
|
|
if (const UPackage* SelectedObjectPackage = SelectedObject->GetOutermost())
|
|
{
|
|
if (WritableFolderFilter->HasFiltering() && !WritableFolderFilter->PassesStartsWithFilter(SelectedObjectPackage->GetFName()))
|
|
{
|
|
ContextObject->bCanBeModified = false;
|
|
break;
|
|
}
|
|
|
|
if (SelectedObjectPackage->HasAnyPackageFlags(PKG_Cooked | PKG_FilterEditorOnly))
|
|
{
|
|
ContextObject->bCanBeModified = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (const UClass* AssetClass = SelectedObject->GetClass())
|
|
{
|
|
if (AssetClass->IsChildOf<UClass>())
|
|
{
|
|
ContextObject->bCanBeModified = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
MenuName = UToolMenus::JoinMenuPaths(BaseMenuName, CommonClass->GetFName());
|
|
|
|
RegisterMenuHierarchy(CommonClass);
|
|
|
|
// Find asset actions for common class
|
|
TSharedPtr<IAssetTypeActions> CommonAssetTypeActions = AssetToolsModule.Get().GetAssetTypeActionsForClass(ContextObject->CommonClass).Pin();
|
|
if (CommonAssetTypeActions.IsValid() && CommonAssetTypeActions->HasActions(SelectedObjects))
|
|
{
|
|
ContextObject->CommonAssetTypeActions = CommonAssetTypeActions;
|
|
}
|
|
}
|
|
else if (SelectedObjects.Num() == 0)
|
|
{
|
|
if (CommonDataSource)
|
|
{
|
|
ContextObject->bCanBeModified = true;
|
|
|
|
if (WritableFolderFilter->HasFiltering())
|
|
{
|
|
for (const FContentBrowserItem& SelectedItem : SelectedItems)
|
|
{
|
|
if (!WritableFolderFilter->PassesStartsWithFilter(SelectedItem.GetVirtualPath()))
|
|
{
|
|
ContextObject->bCanBeModified = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
MenuName = UToolMenus::JoinMenuPaths(ItemContextMenuName, CommonDataSource->GetFName());
|
|
|
|
if (!ToolMenus->IsMenuRegistered(MenuName))
|
|
{
|
|
ToolMenus->RegisterMenu(MenuName, BaseMenuName);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
FToolMenuContext MenuContext(InCommandList, MenuExtender, ContextObject);
|
|
|
|
{
|
|
UContentBrowserDataMenuContext_FileMenu* DataContextObject = NewObject<UContentBrowserDataMenuContext_FileMenu>();
|
|
DataContextObject->SelectedItems = SelectedItems;
|
|
DataContextObject->SelectedCollections = SourcesData.Collections;
|
|
DataContextObject->bCanBeModified = ContextObject->bCanBeModified;
|
|
DataContextObject->ParentWidget = AssetView;
|
|
DataContextObject->OnShowInPathsView = OnShowInPathsViewRequested;
|
|
DataContextObject->OnRefreshView = OnAssetViewRefreshRequested;
|
|
MenuContext.AddObject(DataContextObject);
|
|
}
|
|
|
|
return ToolMenus->GenerateWidget(MenuName, MenuContext);
|
|
}
|
|
|
|
void FAssetContextMenu::RegisterMenuHierarchy(UClass* InClass)
|
|
{
|
|
static const FName BaseMenuName("ContentBrowser.AssetContextMenu");
|
|
|
|
UToolMenus* ToolMenus = UToolMenus::Get();
|
|
|
|
for (UClass* CurrentClass = InClass; CurrentClass; CurrentClass = CurrentClass->GetSuperClass())
|
|
{
|
|
FName CurrentMenuName = UToolMenus::JoinMenuPaths(BaseMenuName, CurrentClass->GetFName());
|
|
if (!ToolMenus->IsMenuRegistered(CurrentMenuName))
|
|
{
|
|
FName ParentMenuName;
|
|
UClass* ParentClass = CurrentClass->GetSuperClass();
|
|
if (ParentClass == UObject::StaticClass() || ParentClass == nullptr)
|
|
{
|
|
ParentMenuName = BaseMenuName;
|
|
}
|
|
else
|
|
{
|
|
ParentMenuName = UToolMenus::JoinMenuPaths(BaseMenuName, ParentClass->GetFName());
|
|
}
|
|
|
|
ToolMenus->RegisterMenu(CurrentMenuName, ParentMenuName);
|
|
|
|
if (ParentMenuName == BaseMenuName)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void FAssetContextMenu::RegisterContextMenu(const FName MenuName)
|
|
{
|
|
UToolMenus* ToolMenus = UToolMenus::Get();
|
|
if (!ToolMenus->IsMenuRegistered(MenuName))
|
|
{
|
|
UToolMenu* Menu = ToolMenus->RegisterMenu(MenuName);
|
|
FToolMenuSection& Section = Menu->FindOrAddSection("GetAssetActions");
|
|
|
|
// Note: Do not use "GetActions" again when copying this code, otherwise "GetActions" menu entry will be overwritten
|
|
Section.AddDynamicEntry("GetActions", FNewToolMenuSectionDelegate::CreateLambda([](FToolMenuSection& InSection)
|
|
{
|
|
UContentBrowserAssetContextMenuContext* Context = InSection.FindContext<UContentBrowserAssetContextMenuContext>();
|
|
if (Context && Context->CommonAssetTypeActions.IsValid())
|
|
{
|
|
Context->CommonAssetTypeActions.Pin()->GetActions(Context->GetSelectedObjects(), InSection);
|
|
}
|
|
}));
|
|
|
|
Section.AddDynamicEntry("GetActionsLegacy", FNewToolMenuDelegateLegacy::CreateLambda([](FMenuBuilder& MenuBuilder, UToolMenu* InMenu)
|
|
{
|
|
UContentBrowserAssetContextMenuContext* Context = InMenu->FindContext<UContentBrowserAssetContextMenuContext>();
|
|
if (Context && Context->CommonAssetTypeActions.IsValid())
|
|
{
|
|
Context->CommonAssetTypeActions.Pin()->GetActions(Context->GetSelectedObjects(), MenuBuilder);
|
|
}
|
|
}));
|
|
|
|
Menu->AddDynamicSection("AddMenuOptions", FNewToolMenuDelegate::CreateLambda([](UToolMenu* InMenu)
|
|
{
|
|
UContentBrowserAssetContextMenuContext* Context = InMenu->FindContext<UContentBrowserAssetContextMenuContext>();
|
|
if (Context && Context->AssetContextMenu.IsValid())
|
|
{
|
|
Context->AssetContextMenu.Pin()->AddMenuOptions(InMenu);
|
|
}
|
|
}));
|
|
}
|
|
}
|
|
|
|
void FAssetContextMenu::AddMenuOptions(UToolMenu* InMenu)
|
|
{
|
|
UContentBrowserDataMenuContext_FileMenu* Context = InMenu->FindContext<UContentBrowserDataMenuContext_FileMenu>();
|
|
const bool bCanBeModified = !Context || Context->bCanBeModified;
|
|
|
|
// Add any type-specific context menu options
|
|
AddAssetTypeMenuOptions(InMenu);
|
|
|
|
// Add quick access to common commands.
|
|
AddCommonMenuOptions(InMenu);
|
|
|
|
// Add quick access to view commands
|
|
AddExploreMenuOptions(InMenu);
|
|
|
|
if (ContentBrowserConsoleVariables::ContentBrowser_EnablePublicAssetFeature)
|
|
{
|
|
AddPublicStateMenuOptions(InMenu);
|
|
}
|
|
|
|
// Add reference options
|
|
AddReferenceMenuOptions(InMenu);
|
|
|
|
// Add collection options
|
|
if (bCanBeModified)
|
|
{
|
|
AddCollectionMenuOptions(InMenu);
|
|
}
|
|
}
|
|
|
|
void FAssetContextMenu::SetSelectedItems(TArrayView<const FContentBrowserItem> InSelectedItems)
|
|
{
|
|
SelectedItems.Reset();
|
|
SelectedItems.Append(InSelectedItems.GetData(), InSelectedItems.Num());
|
|
|
|
SelectedFiles.Reset();
|
|
SelectedFolders.Reset();
|
|
for (const FContentBrowserItem& SelectedItem : SelectedItems)
|
|
{
|
|
if (SelectedItem.IsFile())
|
|
{
|
|
SelectedFiles.Add(SelectedItem);
|
|
}
|
|
|
|
if (SelectedItem.IsFolder())
|
|
{
|
|
SelectedFolders.Add(SelectedItem);
|
|
}
|
|
}
|
|
}
|
|
|
|
void FAssetContextMenu::SetOnShowInPathsViewRequested(const FOnShowInPathsViewRequested& InOnShowInPathsViewRequested)
|
|
{
|
|
OnShowInPathsViewRequested = InOnShowInPathsViewRequested;
|
|
}
|
|
|
|
void FAssetContextMenu::SetOnRenameRequested(const FOnRenameRequested& InOnRenameRequested)
|
|
{
|
|
OnRenameRequested = InOnRenameRequested;
|
|
}
|
|
|
|
void FAssetContextMenu::SetOnDuplicateRequested(const FOnDuplicateRequested& InOnDuplicateRequested)
|
|
{
|
|
OnDuplicateRequested = InOnDuplicateRequested;
|
|
}
|
|
|
|
void FAssetContextMenu::SetOnEditRequested(const FOnEditRequested& InOnEditRequested)
|
|
{
|
|
OnEditRequested = InOnEditRequested;
|
|
}
|
|
|
|
void FAssetContextMenu::SetOnAssetViewRefreshRequested(const FOnAssetViewRefreshRequested& InOnAssetViewRefreshRequested)
|
|
{
|
|
OnAssetViewRefreshRequested = InOnAssetViewRefreshRequested;
|
|
}
|
|
|
|
bool FAssetContextMenu::AddCommonMenuOptions(UToolMenu* Menu)
|
|
{
|
|
UContentBrowserDataMenuContext_FileMenu* Context = Menu->FindContext<UContentBrowserDataMenuContext_FileMenu>();
|
|
const bool bCanBeModified = !Context || Context->bCanBeModified;
|
|
|
|
{
|
|
FToolMenuSection& Section = Menu->AddSection("CommonAssetActions", LOCTEXT("CommonAssetActionsMenuHeading", "Common"));
|
|
|
|
|
|
if (bCanBeModified)
|
|
{
|
|
// Edit
|
|
Section.AddMenuEntry(
|
|
"EditAsset",
|
|
LOCTEXT("EditAsset", "Edit..."),
|
|
LOCTEXT("EditAssetTooltip", "Opens the selected item(s) for edit."),
|
|
FSlateIcon(FAppStyle::GetAppStyleSetName(), "Icons.Edit"),
|
|
FUIAction(
|
|
FExecuteAction::CreateSP(this, &FAssetContextMenu::ExecuteEditItems),
|
|
FCanExecuteAction::CreateSP(this, &FAssetContextMenu::CanExecuteEditItems)
|
|
)
|
|
);
|
|
|
|
// Rename
|
|
Section.AddMenuEntry(FGenericCommands::Get().Rename,
|
|
LOCTEXT("Rename", "Rename"),
|
|
LOCTEXT("RenameTooltip", "Rename the selected item.")
|
|
);
|
|
|
|
// Duplicate
|
|
Section.AddMenuEntry(FGenericCommands::Get().Duplicate,
|
|
LOCTEXT("Duplicate", "Duplicate"),
|
|
LOCTEXT("DuplicateTooltip", "Create a copy of the selected item(s)."),
|
|
FSlateIcon(FAppStyle::GetAppStyleSetName(), "Icons.Duplicate")
|
|
);
|
|
|
|
// Save
|
|
Section.AddMenuEntry(FContentBrowserCommands::Get().SaveSelectedAsset,
|
|
LOCTEXT("SaveAsset", "Save"),
|
|
LOCTEXT("SaveAssetTooltip", "Saves the item to file."),
|
|
FSlateIcon(FAppStyle::GetAppStyleSetName(), "Icons.Save")
|
|
);
|
|
|
|
// Delete
|
|
Section.AddMenuEntry(FGenericCommands::Get().Delete,
|
|
LOCTEXT("Delete", "Delete"),
|
|
TAttribute<FText>::Create(TAttribute<FText>::FGetter::CreateSP(this, &FAssetContextMenu::GetDeleteToolTip))
|
|
);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void FAssetContextMenu::AddExploreMenuOptions(UToolMenu* Menu)
|
|
{
|
|
FToolMenuSection& Section = Menu->AddSection("AssetContextExploreMenuOptions", LOCTEXT("AssetContextExploreMenuOptionsHeading", "Explore"));
|
|
{
|
|
// Find in Content Browser
|
|
Section.AddMenuEntry(
|
|
FGlobalEditorCommonCommands::Get().FindInContentBrowser,
|
|
LOCTEXT("ShowInFolderView", "Show in Folder View"),
|
|
LOCTEXT("ShowInFolderViewTooltip", "Selects the folder that contains this asset in the Content Browser Sources Panel.")
|
|
);
|
|
|
|
// Find in Explorer
|
|
Section.AddMenuEntry(
|
|
"FindInExplorer",
|
|
ContentBrowserUtils::GetExploreFolderText(),
|
|
LOCTEXT("FindInExplorerTooltip", "Finds this asset on disk"),
|
|
FSlateIcon(FAppStyle::GetAppStyleSetName(), "ContentBrowser.ShowInExplorer"),
|
|
FUIAction(
|
|
FExecuteAction::CreateSP(this, &FAssetContextMenu::ExecuteFindInExplorer),
|
|
FCanExecuteAction::CreateSP(this, &FAssetContextMenu::CanExecuteFindInExplorer)
|
|
)
|
|
);
|
|
}
|
|
}
|
|
|
|
bool FAssetContextMenu::AddPublicStateMenuOptions(UToolMenu* Menu)
|
|
{
|
|
if (!bCanExecutePublicAssetToggle && !bCanExecuteBulkSetPublicAsset)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
UContentBrowserDataMenuContext_FileMenu* Context = Menu->FindContext<UContentBrowserDataMenuContext_FileMenu>();
|
|
{
|
|
FToolMenuSection& Section = Menu->AddSection("AssetPublicState", LOCTEXT("PublicStateHandling", "Asset State"));
|
|
|
|
if (SelectedFiles.Num() == 1 && bCanExecutePublicAssetToggle)
|
|
{
|
|
Section.AddMenuEntry(
|
|
"PublicAsset",
|
|
LOCTEXT("PublicAssetToggle", "Public Asset"),
|
|
LOCTEXT("PublicAssetToggleTooltip", "Sets the asset to be referencable by other Plugins"),
|
|
FSlateIcon(),
|
|
FUIAction(
|
|
FExecuteAction::CreateSP(this, &FAssetContextMenu::ExecutePublicAssetToggle),
|
|
FCanExecuteAction::CreateSP(this, &FAssetContextMenu::CanExecutePublicAssetToggle),
|
|
FIsActionChecked::CreateSP(this, &FAssetContextMenu::IsSelectedAssetPublic)
|
|
),
|
|
EUserInterfaceActionType::RadioButton
|
|
);
|
|
|
|
Section.AddMenuEntry(
|
|
"PrivateAsset",
|
|
LOCTEXT("SetPrivateAsset", "Private Asset"),
|
|
LOCTEXT("SetAssetPrivateTooltip", "Sets the asset so it can't be referenced by other Plugins"),
|
|
FSlateIcon(),
|
|
FUIAction(
|
|
FExecuteAction::CreateSP(this, &FAssetContextMenu::ExecutePublicAssetToggle),
|
|
FCanExecuteAction::CreateSP(this, &FAssetContextMenu::CanExecutePublicAssetToggle),
|
|
FIsActionChecked::CreateSP(this, &FAssetContextMenu::IsSelectedAssetPrivate)
|
|
),
|
|
EUserInterfaceActionType::RadioButton
|
|
);
|
|
}
|
|
else if (SelectedFiles.Num() > 1 && bCanExecuteBulkSetPublicAsset)
|
|
{
|
|
Section.AddMenuEntry(
|
|
"MarkSelectedAsPublic",
|
|
LOCTEXT("MarkSelectedAsPublic", "Mark Selected As Public"),
|
|
LOCTEXT("MarkSelectedAsPublicTooltip", "Sets all selected assets to be publicly available for reference by other plugins"),
|
|
FSlateIcon(FAppStyle::GetAppStyleSetName(), "ContentBrowser.AssetActions.PublicAssetToggle"),
|
|
FUIAction(
|
|
FExecuteAction::CreateSP(this, &FAssetContextMenu::ExecuteBulkSetPublicAsset),
|
|
FCanExecuteAction::CreateSP(this, &FAssetContextMenu::CanExecuteBulkSetPublicAsset)
|
|
)
|
|
);
|
|
|
|
Section.AddMenuEntry(
|
|
"MarkSelectedAsPrivate",
|
|
LOCTEXT("MarkSelectedAsPrivate", "Mark Selected As Private"),
|
|
LOCTEXT("MarkSelectedAsPrivateTooltip", "Sets all selected assets to be private and unavailable for reference by other plugins"),
|
|
FSlateIcon(FAppStyle::GetAppStyleSetName(), "ContentBrowser.AssetActions.PublicAssetToggle"),
|
|
FUIAction(
|
|
FExecuteAction::CreateSP(this, &FAssetContextMenu::ExecuteBulkUnsetPublicAsset),
|
|
FCanExecuteAction::CreateSP(this, &FAssetContextMenu::CanExecuteBulkSetPublicAsset)
|
|
)
|
|
);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool FAssetContextMenu::AddReferenceMenuOptions(UToolMenu* Menu)
|
|
{
|
|
UContentBrowserDataMenuContext_FileMenu* Context = Menu->FindContext<UContentBrowserDataMenuContext_FileMenu>();
|
|
{
|
|
FToolMenuSection& Section = Menu->AddSection("AssetContextReferences", LOCTEXT("ReferencesMenuHeading", "References"));
|
|
|
|
Section.AddMenuEntry(
|
|
"CopyReference",
|
|
LOCTEXT("CopyReference", "Copy Reference"),
|
|
LOCTEXT("CopyReferenceTooltip", "Copies reference paths for the selected assets to the clipboard."),
|
|
FSlateIcon(FAppStyle::GetAppStyleSetName(), "GenericCommands.Copy"),
|
|
FUIAction( FExecuteAction::CreateSP( this, &FAssetContextMenu::ExecuteCopyReference ) )
|
|
);
|
|
|
|
if (Context->bCanBeModified)
|
|
{
|
|
Section.AddMenuEntry(
|
|
"CopyFilePath",
|
|
LOCTEXT("CopyFilePath", "Copy File Path"),
|
|
LOCTEXT("CopyFilePathTooltip", "Copies the file paths on disk for the selected assets to the clipboard."),
|
|
FSlateIcon(FAppStyle::GetAppStyleSetName(), "GenericCommands.Copy"),
|
|
FUIAction(FExecuteAction::CreateSP(this, &FAssetContextMenu::ExecuteCopyFilePath))
|
|
);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool FAssetContextMenu::AddAssetTypeMenuOptions(UToolMenu* Menu)
|
|
{
|
|
bool bAnyTypeOptions = false;
|
|
|
|
UContentBrowserAssetContextMenuContext* Context = Menu->FindContext<UContentBrowserAssetContextMenuContext>();
|
|
if (Context && Context->SelectedObjects.Num() > 0)
|
|
{
|
|
// Label "GetAssetActions" section
|
|
FToolMenuSection& Section = Menu->FindOrAddSection("GetAssetActions");
|
|
if (Context->CommonAssetTypeActions.IsValid())
|
|
{
|
|
Section.Label = FText::Format(NSLOCTEXT("AssetTools", "AssetSpecificOptionsMenuHeading", "{0} Actions"), Context->CommonAssetTypeActions.Pin()->GetName());
|
|
}
|
|
else if (Context->CommonClass)
|
|
{
|
|
Section.Label = FText::Format(NSLOCTEXT("AssetTools", "AssetSpecificOptionsMenuHeading", "{0} Actions"), FText::FromName(Context->CommonClass->GetFName()));
|
|
}
|
|
else
|
|
{
|
|
Section.Label = FText::Format(NSLOCTEXT("AssetTools", "AssetSpecificOptionsMenuHeading", "{0} Actions"), FText::FromString(TEXT("Asset")));
|
|
}
|
|
|
|
bAnyTypeOptions = true;
|
|
}
|
|
|
|
return bAnyTypeOptions;
|
|
}
|
|
|
|
bool FAssetContextMenu::AddCollectionMenuOptions(UToolMenu* Menu)
|
|
{
|
|
class FManageCollectionsContextMenu
|
|
{
|
|
public:
|
|
static void CreateManageCollectionsSubMenu(UToolMenu* SubMenu, TSharedRef<FCollectionAssetManagement> QuickAssetManagement)
|
|
{
|
|
FCollectionManagerModule& CollectionManagerModule = FCollectionManagerModule::GetModule();
|
|
|
|
TArray<FCollectionNameType> AvailableCollections;
|
|
CollectionManagerModule.Get().GetRootCollections(AvailableCollections);
|
|
|
|
CreateManageCollectionsSubMenu(SubMenu, QuickAssetManagement, MoveTemp(AvailableCollections));
|
|
}
|
|
|
|
static void CreateManageCollectionsSubMenu(UToolMenu* SubMenu, TSharedRef<FCollectionAssetManagement> QuickAssetManagement, TArray<FCollectionNameType> AvailableCollections)
|
|
{
|
|
FCollectionManagerModule& CollectionManagerModule = FCollectionManagerModule::GetModule();
|
|
|
|
AvailableCollections.Sort([](const FCollectionNameType& One, const FCollectionNameType& Two) -> bool
|
|
{
|
|
return One.Name.LexicalLess(Two.Name);
|
|
});
|
|
|
|
FToolMenuSection& Section = SubMenu->AddSection("Section");
|
|
for (const FCollectionNameType& AvailableCollection : AvailableCollections)
|
|
{
|
|
// Never display system collections
|
|
if (AvailableCollection.Type == ECollectionShareType::CST_System)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// Can only manage assets for static collections
|
|
ECollectionStorageMode::Type StorageMode = ECollectionStorageMode::Static;
|
|
CollectionManagerModule.Get().GetCollectionStorageMode(AvailableCollection.Name, AvailableCollection.Type, StorageMode);
|
|
if (StorageMode != ECollectionStorageMode::Static)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
TArray<FCollectionNameType> AvailableChildCollections;
|
|
CollectionManagerModule.Get().GetChildCollections(AvailableCollection.Name, AvailableCollection.Type, AvailableChildCollections);
|
|
|
|
if (AvailableChildCollections.Num() > 0)
|
|
{
|
|
Section.AddSubMenu(
|
|
NAME_None,
|
|
FText::FromName(AvailableCollection.Name),
|
|
FText::GetEmpty(),
|
|
FNewToolMenuDelegate::CreateStatic(&FManageCollectionsContextMenu::CreateManageCollectionsSubMenu, QuickAssetManagement, AvailableChildCollections),
|
|
FUIAction(
|
|
FExecuteAction::CreateStatic(&FManageCollectionsContextMenu::OnCollectionClicked, QuickAssetManagement, AvailableCollection),
|
|
FCanExecuteAction::CreateStatic(&FManageCollectionsContextMenu::IsCollectionEnabled, QuickAssetManagement, AvailableCollection),
|
|
FGetActionCheckState::CreateStatic(&FManageCollectionsContextMenu::GetCollectionCheckState, QuickAssetManagement, AvailableCollection)
|
|
),
|
|
EUserInterfaceActionType::ToggleButton,
|
|
false,
|
|
FSlateIcon(FAppStyle::GetAppStyleSetName(), ECollectionShareType::GetIconStyleName(AvailableCollection.Type))
|
|
);
|
|
}
|
|
else
|
|
{
|
|
Section.AddMenuEntry(
|
|
NAME_None,
|
|
FText::FromName(AvailableCollection.Name),
|
|
FText::GetEmpty(),
|
|
FSlateIcon(FAppStyle::GetAppStyleSetName(), ECollectionShareType::GetIconStyleName(AvailableCollection.Type)),
|
|
FUIAction(
|
|
FExecuteAction::CreateStatic(&FManageCollectionsContextMenu::OnCollectionClicked, QuickAssetManagement, AvailableCollection),
|
|
FCanExecuteAction::CreateStatic(&FManageCollectionsContextMenu::IsCollectionEnabled, QuickAssetManagement, AvailableCollection),
|
|
FGetActionCheckState::CreateStatic(&FManageCollectionsContextMenu::GetCollectionCheckState, QuickAssetManagement, AvailableCollection)
|
|
),
|
|
EUserInterfaceActionType::ToggleButton
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
private:
|
|
static bool IsCollectionEnabled(TSharedRef<FCollectionAssetManagement> QuickAssetManagement, FCollectionNameType InCollectionKey)
|
|
{
|
|
return QuickAssetManagement->IsCollectionEnabled(InCollectionKey);
|
|
}
|
|
|
|
static ECheckBoxState GetCollectionCheckState(TSharedRef<FCollectionAssetManagement> QuickAssetManagement, FCollectionNameType InCollectionKey)
|
|
{
|
|
return QuickAssetManagement->GetCollectionCheckState(InCollectionKey);
|
|
}
|
|
|
|
static void OnCollectionClicked(TSharedRef<FCollectionAssetManagement> QuickAssetManagement, FCollectionNameType InCollectionKey)
|
|
{
|
|
// The UI actions don't give you the new check state, so we need to emulate the behavior of SCheckBox
|
|
// Basically, checked will transition to unchecked (removing items), and anything else will transition to checked (adding items)
|
|
if (GetCollectionCheckState(QuickAssetManagement, InCollectionKey) == ECheckBoxState::Checked)
|
|
{
|
|
QuickAssetManagement->RemoveCurrentAssetsFromCollection(InCollectionKey);
|
|
}
|
|
else
|
|
{
|
|
QuickAssetManagement->AddCurrentAssetsToCollection(InCollectionKey);
|
|
}
|
|
}
|
|
};
|
|
|
|
bool bHasAddedItems = false;
|
|
|
|
FCollectionManagerModule& CollectionManagerModule = FCollectionManagerModule::GetModule();
|
|
|
|
FToolMenuSection& Section = Menu->AddSection("AssetContextCollections", LOCTEXT("AssetCollectionOptionsMenuHeading", "Collections"));
|
|
|
|
// Show a sub-menu that allows you to quickly add or remove the current asset selection from the available collections
|
|
if (CollectionManagerModule.Get().HasCollections())
|
|
{
|
|
TSharedRef<FCollectionAssetManagement> QuickAssetManagement = MakeShared<FCollectionAssetManagement>();
|
|
|
|
TArray<FName> SelectedItemCollectionIds;
|
|
for (const FContentBrowserItem& SelectedItem : SelectedFiles)
|
|
{
|
|
FName ItemCollectionId;
|
|
if (SelectedItem.TryGetCollectionId(ItemCollectionId))
|
|
{
|
|
SelectedItemCollectionIds.Add(ItemCollectionId);
|
|
}
|
|
}
|
|
QuickAssetManagement->SetCurrentAssetPaths(SelectedItemCollectionIds);
|
|
|
|
Section.AddSubMenu(
|
|
"ManageCollections",
|
|
LOCTEXT("ManageCollections", "Manage Collections"),
|
|
FText::Format(LOCTEXT("ManageCollections_ToolTip", "Manage the collections that the selected {0}|plural(one=item belongs, other=items belong) to."), SelectedFiles.Num()),
|
|
FNewToolMenuDelegate::CreateStatic(&FManageCollectionsContextMenu::CreateManageCollectionsSubMenu, QuickAssetManagement),
|
|
false, // default value
|
|
FSlateIcon(FAppStyle::GetAppStyleSetName(), "ContentBrowser.Collections")
|
|
);
|
|
|
|
bHasAddedItems = true;
|
|
}
|
|
|
|
// "Remove from collection" (only display option if exactly one collection is selected)
|
|
if ( SourcesData.Collections.Num() == 1 && !SourcesData.IsDynamicCollection() )
|
|
{
|
|
Section.AddMenuEntry(
|
|
"RemoveFromCollection",
|
|
FText::Format(LOCTEXT("RemoveFromCollectionFmt", "Remove From {0}"), FText::FromName(SourcesData.Collections[0].Name)),
|
|
LOCTEXT("RemoveFromCollection_ToolTip", "Removes the selected item from the current collection."),
|
|
FSlateIcon(),
|
|
FUIAction(
|
|
FExecuteAction::CreateSP( this, &FAssetContextMenu::ExecuteRemoveFromCollection ),
|
|
FCanExecuteAction::CreateSP( this, &FAssetContextMenu::CanExecuteRemoveFromCollection )
|
|
)
|
|
);
|
|
|
|
bHasAddedItems = true;
|
|
}
|
|
|
|
|
|
return bHasAddedItems;
|
|
}
|
|
|
|
void FAssetContextMenu::ExecuteSyncToAssetTree()
|
|
{
|
|
// Copy this as the sync may adjust our selected assets array
|
|
const TArray<FContentBrowserItem> SelectedFilesCopy = SelectedFiles;
|
|
OnShowInPathsViewRequested.ExecuteIfBound(SelectedFilesCopy);
|
|
}
|
|
|
|
void FAssetContextMenu::ExecuteFindInExplorer()
|
|
{
|
|
ContentBrowserUtils::ExploreFolders(SelectedFiles, AssetView.Pin().ToSharedRef());
|
|
}
|
|
|
|
bool FAssetContextMenu::CanExecuteEditItems() const
|
|
{
|
|
bool bCanEdit = false;
|
|
for (const FContentBrowserItem& SelectedItem : SelectedFiles)
|
|
{
|
|
bCanEdit |= SelectedItem.CanEdit();
|
|
}
|
|
return bCanEdit;
|
|
}
|
|
|
|
void FAssetContextMenu::ExecuteEditItems()
|
|
{
|
|
if (SelectedFiles.Num() > 0)
|
|
{
|
|
OnEditRequested.ExecuteIfBound(SelectedFiles);
|
|
}
|
|
}
|
|
|
|
void FAssetContextMenu::ExecuteSaveAsset()
|
|
{
|
|
const EContentBrowserItemSaveFlags SaveFlags = EContentBrowserItemSaveFlags::SaveOnlyIfLoaded;
|
|
|
|
// Batch these by their data sources
|
|
TMap<UContentBrowserDataSource*, TArray<FContentBrowserItemData>> SourcesAndItems;
|
|
for (const FContentBrowserItem& SelectedItem : SelectedFiles)
|
|
{
|
|
FContentBrowserItem::FItemDataArrayView ItemDataArray = SelectedItem.GetInternalItems();
|
|
for (const FContentBrowserItemData& ItemData : ItemDataArray)
|
|
{
|
|
if (UContentBrowserDataSource* ItemDataSource = ItemData.GetOwnerDataSource())
|
|
{
|
|
FText SaveErrorMsg;
|
|
if (ItemDataSource->CanSaveItem(ItemData, SaveFlags, &SaveErrorMsg))
|
|
{
|
|
TArray<FContentBrowserItemData>& ItemsForSource = SourcesAndItems.FindOrAdd(ItemDataSource);
|
|
ItemsForSource.Add(ItemData);
|
|
}
|
|
else
|
|
{
|
|
AssetViewUtils::ShowErrorNotifcation(SaveErrorMsg);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Execute the operation now
|
|
for (const auto& SourceAndItemsPair : SourcesAndItems)
|
|
{
|
|
SourceAndItemsPair.Key->BulkSaveItems(SourceAndItemsPair.Value, SaveFlags);
|
|
}
|
|
}
|
|
|
|
void FAssetContextMenu::ExecuteDuplicate()
|
|
{
|
|
if (SelectedFiles.Num() > 0)
|
|
{
|
|
OnDuplicateRequested.ExecuteIfBound(SelectedFiles);
|
|
}
|
|
}
|
|
|
|
void FAssetContextMenu::ExecuteRename(EContentBrowserViewContext ViewContext)
|
|
{
|
|
if (SelectedItems.Num() == 1)
|
|
{
|
|
OnRenameRequested.ExecuteIfBound(SelectedItems[0], ViewContext);
|
|
}
|
|
}
|
|
|
|
void FAssetContextMenu::ExecuteDelete()
|
|
{
|
|
// Batch these by their data sources
|
|
TMap<UContentBrowserDataSource*, TArray<FContentBrowserItemData>> SourcesAndItems;
|
|
for (const FContentBrowserItem& SelectedItem : SelectedFiles)
|
|
{
|
|
FContentBrowserItem::FItemDataArrayView ItemDataArray = SelectedItem.GetInternalItems();
|
|
for (const FContentBrowserItemData& ItemData : ItemDataArray)
|
|
{
|
|
if (UContentBrowserDataSource* ItemDataSource = ItemData.GetOwnerDataSource())
|
|
{
|
|
FText DeleteErrorMsg;
|
|
if (ItemDataSource->CanDeleteItem(ItemData, &DeleteErrorMsg))
|
|
{
|
|
TArray<FContentBrowserItemData>& ItemsForSource = SourcesAndItems.FindOrAdd(ItemDataSource);
|
|
ItemsForSource.Add(ItemData);
|
|
}
|
|
else
|
|
{
|
|
AssetViewUtils::ShowErrorNotifcation(DeleteErrorMsg);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Execute the operation now
|
|
for (const auto& SourceAndItemsPair : SourcesAndItems)
|
|
{
|
|
SourceAndItemsPair.Key->BulkDeleteItems(SourceAndItemsPair.Value);
|
|
}
|
|
|
|
// If we had any folders selected, ask the user whether they want to delete them
|
|
// as it can be slow to build the deletion dialog on an accidental click
|
|
if (SelectedFolders.Num() > 0)
|
|
{
|
|
FText Prompt;
|
|
if (SelectedFolders.Num() == 1)
|
|
{
|
|
Prompt = FText::Format(LOCTEXT("FolderDeleteConfirm_Single", "Delete folder '{0}'?"), SelectedFolders[0].GetDisplayName());
|
|
}
|
|
else
|
|
{
|
|
Prompt = FText::Format(LOCTEXT("FolderDeleteConfirm_Multiple", "Delete {0} folders?"), 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()
|
|
{
|
|
// Batch these by their data sources
|
|
TMap<UContentBrowserDataSource*, TArray<FContentBrowserItemData>> SourcesAndItems;
|
|
for (const FContentBrowserItem& SelectedItem : SelectedFolders)
|
|
{
|
|
FContentBrowserItem::FItemDataArrayView ItemDataArray = SelectedItem.GetInternalItems();
|
|
for (const FContentBrowserItemData& ItemData : ItemDataArray)
|
|
{
|
|
if (UContentBrowserDataSource* ItemDataSource = ItemData.GetOwnerDataSource())
|
|
{
|
|
FText DeleteErrorMsg;
|
|
if (ItemDataSource->CanDeleteItem(ItemData, &DeleteErrorMsg))
|
|
{
|
|
TArray<FContentBrowserItemData>& ItemsForSource = SourcesAndItems.FindOrAdd(ItemDataSource);
|
|
ItemsForSource.Add(ItemData);
|
|
}
|
|
else
|
|
{
|
|
AssetViewUtils::ShowErrorNotifcation(DeleteErrorMsg);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Execute the operation now
|
|
for (const auto& SourceAndItemsPair : SourcesAndItems)
|
|
{
|
|
SourceAndItemsPair.Key->BulkDeleteItems(SourceAndItemsPair.Value);
|
|
}
|
|
|
|
return FReply::Handled();
|
|
}
|
|
|
|
void FAssetContextMenu::ExecutePublicAssetToggle()
|
|
{
|
|
// Toggle selected files public asset flag
|
|
if (ensure(SelectedFiles.Num() == 1))
|
|
{
|
|
FAssetData ItemAssetData;
|
|
if (SelectedFiles[0].Legacy_TryGetAssetData(ItemAssetData))
|
|
{
|
|
UPackage* ItemAssetPackage = ItemAssetData.GetPackage();
|
|
|
|
if (!ItemAssetPackage)
|
|
{
|
|
return;
|
|
}
|
|
|
|
ItemAssetPackage->SetIsExternallyReferenceable(!ItemAssetPackage->IsExternallyReferenceable());
|
|
|
|
ItemAssetPackage->Modify();
|
|
|
|
OnAssetViewRefreshRequested.ExecuteIfBound();
|
|
}
|
|
}
|
|
}
|
|
|
|
bool FAssetContextMenu::CanExecutePublicAssetToggle()
|
|
{
|
|
return bCanExecutePublicAssetToggle;
|
|
}
|
|
|
|
void FAssetContextMenu::ExecuteBulkSetPublicAsset()
|
|
{
|
|
for (const FContentBrowserItem& SelectedItem : SelectedFiles)
|
|
{
|
|
FAssetData ItemAssetData;
|
|
if (SelectedItem.Legacy_TryGetAssetData(ItemAssetData))
|
|
{
|
|
UPackage* ItemAssetPackage = ItemAssetData.GetPackage();
|
|
|
|
if (!ItemAssetPackage)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (!ItemAssetPackage->IsExternallyReferenceable())
|
|
{
|
|
ItemAssetPackage->SetIsExternallyReferenceable(true);
|
|
|
|
ItemAssetPackage->Modify();
|
|
}
|
|
}
|
|
}
|
|
|
|
OnAssetViewRefreshRequested.ExecuteIfBound();
|
|
}
|
|
|
|
void FAssetContextMenu::ExecuteBulkUnsetPublicAsset()
|
|
{
|
|
for (const FContentBrowserItem& SelectedItem : SelectedFiles)
|
|
{
|
|
FAssetData ItemAssetData;
|
|
if (SelectedItem.Legacy_TryGetAssetData(ItemAssetData))
|
|
{
|
|
UPackage* ItemAssetPackage = ItemAssetData.GetPackage();
|
|
|
|
if (!ItemAssetPackage)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (ItemAssetPackage->IsExternallyReferenceable())
|
|
{
|
|
ItemAssetPackage->SetIsExternallyReferenceable(false);
|
|
|
|
ItemAssetPackage->Modify();
|
|
}
|
|
}
|
|
}
|
|
|
|
OnAssetViewRefreshRequested.ExecuteIfBound();
|
|
}
|
|
|
|
bool FAssetContextMenu::CanExecuteBulkSetPublicAsset()
|
|
{
|
|
return bCanExecuteBulkSetPublicAsset;
|
|
}
|
|
|
|
bool FAssetContextMenu::IsSelectedAssetPublic()
|
|
{
|
|
if (ensure(SelectedFiles.Num() == 1))
|
|
{
|
|
FAssetData ItemAssetData;
|
|
if (SelectedFiles[0].Legacy_TryGetAssetData(ItemAssetData))
|
|
{
|
|
UPackage* ItemAssetPackage = ItemAssetData.GetPackage();
|
|
|
|
if (ItemAssetPackage)
|
|
{
|
|
return ItemAssetPackage->IsExternallyReferenceable();
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool FAssetContextMenu::IsSelectedAssetPrivate()
|
|
{
|
|
return !IsSelectedAssetPublic();
|
|
}
|
|
|
|
void FAssetContextMenu::ExecuteCopyReference()
|
|
{
|
|
if (SelectedFiles.Num() > 0)
|
|
{
|
|
ContentBrowserUtils::CopyItemReferencesToClipboard(SelectedFiles);
|
|
}
|
|
}
|
|
|
|
void FAssetContextMenu::ExecuteCopyFilePath()
|
|
{
|
|
if (SelectedFiles.Num() > 0)
|
|
{
|
|
ContentBrowserUtils::CopyFilePathsToClipboard(SelectedFiles);
|
|
}
|
|
}
|
|
|
|
void FAssetContextMenu::ExecuteRemoveFromCollection()
|
|
{
|
|
if ( ensure(SourcesData.Collections.Num() == 1) )
|
|
{
|
|
TArray<FName> SelectedItemCollectionIds;
|
|
for (const FContentBrowserItem& SelectedItem : SelectedFiles)
|
|
{
|
|
FName ItemCollectionId;
|
|
if (SelectedItem.TryGetCollectionId(ItemCollectionId))
|
|
{
|
|
SelectedItemCollectionIds.Add(ItemCollectionId);
|
|
}
|
|
}
|
|
|
|
if ( SelectedItemCollectionIds.Num() > 0 )
|
|
{
|
|
FCollectionManagerModule& CollectionManagerModule = FCollectionManagerModule::GetModule();
|
|
|
|
const FCollectionNameType& Collection = SourcesData.Collections[0];
|
|
CollectionManagerModule.Get().RemoveFromCollection(Collection.Name, Collection.Type, SelectedItemCollectionIds);
|
|
OnAssetViewRefreshRequested.ExecuteIfBound();
|
|
}
|
|
}
|
|
}
|
|
|
|
bool FAssetContextMenu::CanExecuteSyncToAssetTree() const
|
|
{
|
|
return SelectedFiles.Num() > 0;
|
|
}
|
|
|
|
bool FAssetContextMenu::CanExecuteFindInExplorer() const
|
|
{
|
|
return bCanExecuteFindInExplorer;
|
|
}
|
|
|
|
bool FAssetContextMenu::CanExecuteRemoveFromCollection() const
|
|
{
|
|
return SourcesData.Collections.Num() == 1 && !SourcesData.IsDynamicCollection();
|
|
}
|
|
|
|
bool FAssetContextMenu::CanExecuteDuplicate() const
|
|
{
|
|
bool bCanDuplicate = false;
|
|
for (const FContentBrowserItem& SelectedItem : SelectedFiles)
|
|
{
|
|
bCanDuplicate |= SelectedItem.CanDuplicate();
|
|
}
|
|
return bCanDuplicate;
|
|
}
|
|
|
|
bool FAssetContextMenu::CanExecuteRename() const
|
|
{
|
|
return ContentBrowserUtils::CanRenameFromAssetView(AssetView);
|
|
}
|
|
|
|
bool FAssetContextMenu::CanExecuteDelete() const
|
|
{
|
|
return ContentBrowserUtils::CanDeleteFromAssetView(AssetView);
|
|
}
|
|
|
|
FText FAssetContextMenu::GetDeleteToolTip() const
|
|
{
|
|
FText ErrorMessage;
|
|
if (!ContentBrowserUtils::CanDeleteFromAssetView(AssetView, &ErrorMessage) && !ErrorMessage.IsEmpty())
|
|
{
|
|
return ErrorMessage;
|
|
}
|
|
|
|
return LOCTEXT("DeleteTooltip", "Delete the selected items.");
|
|
}
|
|
|
|
bool FAssetContextMenu::CanExecuteSaveAsset() const
|
|
{
|
|
bool bCanSave = false;
|
|
for (const FContentBrowserItem& SelectedItem : SelectedFiles)
|
|
{
|
|
bCanSave |= SelectedItem.CanSave(EContentBrowserItemSaveFlags::SaveOnlyIfLoaded);
|
|
}
|
|
return bCanSave;
|
|
}
|
|
|
|
void FAssetContextMenu::CacheCanExecuteVars()
|
|
{
|
|
bCanExecuteFindInExplorer = false;
|
|
bCanExecutePublicAssetToggle = false;
|
|
bCanExecuteBulkSetPublicAsset = true;
|
|
|
|
// Selection must contain at least one file that has exists on disk
|
|
for (const FContentBrowserItem& SelectedItem : SelectedFiles)
|
|
{
|
|
FString ItemFilename;
|
|
if (!bCanExecuteFindInExplorer && SelectedItem.GetItemPhysicalPath(ItemFilename) && FPaths::FileExists(ItemFilename))
|
|
{
|
|
bCanExecuteFindInExplorer = true;
|
|
}
|
|
|
|
if(SelectedItem.CanEdit() &&
|
|
FContentBrowserSingleton::Get().IsShowingPrivateContent(FPathViews::GetPath(FNameBuilder(SelectedItem.GetVirtualPath()))))
|
|
{
|
|
bCanExecutePublicAssetToggle = true;
|
|
}
|
|
else
|
|
{
|
|
bCanExecuteBulkSetPublicAsset = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
#undef LOCTEXT_NAMESPACE
|