Files
UnrealEngineUWP/Engine/Source/Editor/ContentBrowser/Public/ContentBrowserMenuContexts.h
nick darnell e85b0cd48c AssetDefinition - This is the seed of a long term replacement of IAssetTypeActions. IAssetTypeActions is woefully inadiquit now. It puts a lot of functionality in one place, which wouldn't be a terrible thing, except for the GetActions, and some of the menu stuff being built into this class. We need to make an effort to not have to load every single asset just to open the context menu you have selected, to-wit, a previous CL made it so that summoning the menu no longer *Had* to load the assets, however several remaining issues remained with the Blueprint Utility Actions, and the fact that we don't "KNOW" if we need to call GetActions for an asset. We could introduce a replacement in the class, but that would just get inherited, causing other issues. So instead the parallel UObject based AssetDefinition now exists. In large part it will probably be very similar to the other one, but several things in it probably need to chnage. For now there is a bridging concept in the form of the AssetDefinitionAssetTypeProxy.
Several amounts of effort went into the newer design of UAssetDefinition to make it easier to change over time, more things are structs now for input and output so additional parameters can be added.

AssetDefinition module is an editor module instead of being a developer module.
AssetDefinition does not include a myraid of things it shouldn't such as the blueprint module and UnrealEd.

#jira UE-165574
#preflight 636c0ec4d0174259cca85e37

[CL 23083536 by nick darnell in ue5-main branch]
2022-11-10 13:13:41 -05:00

249 lines
7.4 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "AssetTypeCategories.h"
#include "Containers/Array.h"
#include "ContentBrowserDelegates.h"
#include "CoreMinimal.h"
#include "Algo/SelectRandomWeighted.h"
#include "HAL/Platform.h"
#include "Templates/SharedPointer.h"
#include "UObject/NameTypes.h"
#include "UObject/Object.h"
#include "UObject/ObjectPtr.h"
#include "UObject/WeakObjectPtrTemplates.h"
#include "ContentBrowserMenuContexts.generated.h"
class FAssetContextMenu;
class IAssetTypeActions;
class SAssetView;
class SContentBrowser;
class SFilterList;
class UClass;
class UAssetDefinition;
struct FFrame;
struct FToolMenuSection;
struct FToolMenuContext;
enum class EIncludeSubclasses : uint8
{
No,
Yes
};
UCLASS()
class CONTENTBROWSER_API UContentBrowserAssetContextMenuContext : public UObject
{
GENERATED_BODY()
public:
TWeakPtr<FAssetContextMenu> AssetContextMenu;
UE_DEPRECATED(5.2, "IAssetTypeActions (CommonAssetTypeActions) is being phased out too much menu related stuff was built into their design that forced loading assets. Please use UAssetDefinition (CommonAssetDefinition).")
TWeakPtr<IAssetTypeActions> CommonAssetTypeActions;
UPROPERTY()
TObjectPtr<const UAssetDefinition> CommonAssetDefinition;
UE_DEPRECATED(5.1, "Use SelectedAssets now, this field will not contain any objects. You should call LoadSelectedObjects() based on what you need.")
TArray<TWeakObjectPtr<UObject>> SelectedObjects;
/**
* The currently selected assets in the content browser.
*/
UPROPERTY()
TArray<FAssetData> SelectedAssets;
UPROPERTY()
TObjectPtr<UClass> CommonClass;
UPROPERTY()
bool bCanBeModified;
//UE_DEPRECATED(5.2, "GetSelectedObjects has been deprecated. We no longer automatically load assets on right click. Please use SelectedAssets and determine whatever you need for your context menu options without actually loading the assets. When you finally need all or a subset of the selected assets use LoadSelectedAssets or LoadSelectedAssetsIf")
UFUNCTION(BlueprintCallable, Category="Tool Menus", meta=(DeprecatedFunction, DeprecationMessage = "GetSelectedObjects has been deprecated. We no longer automatically load assets on right click. If you can work without loading the assets, please use SelectedAssets. Otherwise call LoadSelectedObjects"))
TArray<UObject*> GetSelectedObjects() const
{
return LoadSelectedObjectsIfNeeded();
}
/**
* Loads the selected assets (if needed) which is based on AssetViewUtils::LoadAssetsIfNeeded, this exists primarily
* for backwards compatability. Reliance on a black box to determine 'neededness' is not recommended, this function
* will likely be deprecated a few versions after GetSelectedObjects.
*/
UFUNCTION(BlueprintCallable, Category="Tool Menus")
TArray<UObject*> LoadSelectedObjectsIfNeeded() const;
/**
* Loads all the selected assets and returns an array of the objects.
*/
UFUNCTION(BlueprintCallable, Category="Tool Menus")
TArray<UObject*> LoadSelectedObjects(TSet<FName> LoadTags) const
{
return LoadSelectedObjects<UObject>(LoadTags);
}
/**
* Loads all the selected assets and returns an array of the ExpectedAssetType.
*/
template<typename ExpectedAssetType>
TArray<ExpectedAssetType*> LoadSelectedObjects(TSet<FName> LoadTags = {}) const
{
return LoadSelectedObjectsIf<ExpectedAssetType>(LoadTags, [](const FAssetData& AssetData){ return true; });
}
/**
* Loads the selected assets if the PredicateFilter returns true, and returns an array of the objects.
*/
template<typename ExpectedAssetType>
TArray<ExpectedAssetType*> LoadSelectedObjectsIf(TFunctionRef<bool(const FAssetData& AssetData)> PredicateFilter) const
{
return LoadSelectedObjectsIf<ExpectedAssetType>({}, PredicateFilter);
}
/**
* Loads the selected assets if the PredicateFilter returns true, and returns an array of the objects.
*/
template<typename ExpectedAssetType>
TArray<ExpectedAssetType*> LoadSelectedObjectsIf(TSet<FName> LoadTags, TFunctionRef<bool(const FAssetData& AssetData)> PredicateFilter) const
{
TArray<ExpectedAssetType*> Result;
Result.Reserve(SelectedAssets.Num());
for (const FAssetData& Asset : SelectedAssets)
{
if (PredicateFilter(Asset))
{
if (UObject* AssetObject = Asset.GetAsset(LoadTags))
{
if (ExpectedAssetType* AssetObjectTyped = Cast<ExpectedAssetType>(AssetObject))
{
Result.Add(AssetObjectTyped);
}
}
}
}
return Result;
}
/**
* Returns a filtered array of assets that are of the desired class and potentially any subclasses.
*/
TArray<FAssetData> GetSelectedAssetsOfType(const UClass* AssetClass, EIncludeSubclasses IncludeSubclasses = EIncludeSubclasses::Yes) const;
/**
* Sometimes you want to write actions that will only operate on a singular selected asset, in those cases you
* can use the following function which will only return a live ptr if it's an instance of that asset type, and
* only one thing is selected.
*/
const FAssetData* GetSingleSelectedAssetOfType(const UClass* AssetClass, EIncludeSubclasses IncludeSubclasses = EIncludeSubclasses::Yes) const;
/**
* Finds the Content Browser MenuContext from a Menu or Section, and returns the context provided there are some
* selected assets.
*/
template<typename MenuOrSectionType>
static const UContentBrowserAssetContextMenuContext* FindContextWithAssets(const MenuOrSectionType& MenuOrSection)
{
const UContentBrowserAssetContextMenuContext* Context = MenuOrSection.template FindContext<UContentBrowserAssetContextMenuContext>();
if (!Context || Context->SelectedAssets.IsEmpty())
{
return nullptr;
}
return Context;
}
};
UCLASS()
class CONTENTBROWSER_API UContentBrowserAssetViewContextMenuContext : public UObject
{
GENERATED_BODY()
public:
TWeakPtr<SContentBrowser> OwningContentBrowser;
TWeakPtr<SAssetView> AssetView;
};
UCLASS()
class CONTENTBROWSER_API UContentBrowserMenuContext : public UObject
{
GENERATED_BODY()
public:
TWeakPtr<SContentBrowser> ContentBrowser;
};
UCLASS()
class CONTENTBROWSER_API UContentBrowserFolderContext : public UContentBrowserMenuContext
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadOnly, Category = "ContentBrowser")
bool bCanBeModified;
UPROPERTY(BlueprintReadOnly, Category = "ContentBrowser")
bool bNoFolderOnDisk;
UPROPERTY(BlueprintReadOnly, Category = "ContentBrowser")
int32 NumAssetPaths;
UPROPERTY(BlueprintReadOnly, Category = "ContentBrowser")
int32 NumClassPaths;
UPROPERTY(BlueprintReadOnly, Category = "ContentBrowser")
TArray<FString> SelectedPackagePaths;
FOnCreateNewFolder OnCreateNewFolder;
const TArray<FString>& GetSelectedPackagePaths() const { return SelectedPackagePaths; }
};
UCLASS()
class CONTENTBROWSER_API UContentBrowserFilterListContext : public UObject
{
GENERATED_BODY()
public:
TWeakPtr<SFilterList> FilterList;
EAssetTypeCategories::Type MenuExpansion;
};
UCLASS()
class CONTENTBROWSER_API UContentBrowserAddNewContextMenuContext : public UObject
{
GENERATED_BODY()
public:
TWeakPtr<SContentBrowser> ContentBrowser;
};
UCLASS()
class CONTENTBROWSER_API UContentBrowserToolbarMenuContext : public UObject
{
GENERATED_BODY()
public:
FName GetCurrentPath() const;
bool CanWriteToCurrentPath() const;
TWeakPtr<SContentBrowser> ContentBrowser;
};
class UToolMenu;
namespace UE::ContentBrowser
{
CONTENTBROWSER_API UToolMenu* ExtendToolMenu_AssetContextMenu(UClass* AssetClass);
CONTENTBROWSER_API UToolMenu* ExtendToolMenu_AssetContextMenu(TSoftClassPtr<UObject> AssetSoftClass);
}