Adding menu entry to content browser asset menu?

For someone looking for more details, there are several things that can go wrong when implementing a menu extender.

First, as @Roy_Wierer.Seda145 mentioned, you can’t make up an arbitrary name for your extender’s ExtensionHook parameter. It has to be predefined by unreal (or probably another extension that runs before you, but I didn’t verify this). For instance, “Asset” won’t work but “CommonAssetActions” will since the latter is predefined by unreal.

You can figure out what those predefine names are by enabling the engine’s developer tool. See this thread.

Second, if you use CreateSP to creating the delegate for AddMenuExtension, you have to remember that CreateSP creates a weak reference to the user object (the suffix SP is confusing as it leads people to think it actually creates a strong shared pointer), and thus when the shared pointer to your extender implementation class goes out of scope, the delegate will become unbound, leading to the extension callback to not be called at all.

An example in this post solves this by storing the shared pointer inside the module instance itself. See the following lines from their example:

// Extension variable contains a copy of selected paths array, you must keep Extension somewhere to prevent it from being deleted/garbage collected!
Extension = MakeShareable(new FContentBrowserMenuExtension(Path));

But I think the better way is to just use a lambda and capture the shared pointer by copy. Here is my approach:

TSharedRef<FExtender> YourModule::CreateExtender(const TArray<FAssetData>& InAssets)
{
	TSharedPtr<FYourExtenderImpl> ExtenderImpl = MakeShareable(new FYourExtenderImpl(InAssets));
	TSharedPtr<FExtender> Extender = MakeShareable(new FExtender);

	Extender->AddMenuExtension(
		"CommonAssetActions",
		EExtensionHook::After,
		{},
		FMenuExtensionDelegate::CreateLambda([ExtenderImpl, this](auto&& ... Args)
		{
			ExtenderImpl->AddMenuEntry(Forward<decltype(Args)>(Args)...);
		}));
	
	return Extender.ToSharedRef();
}