Generating preview thumbnail for custom asset

I’ve been developing a plugin for a custom asset type for the game I’m working on. Currently when an asset of my custom format is imported the preview thumbnail in the content panel is blank. I’d like to generate a thumbnail for it. I haven’t been able to find any documentation for how to do so.

I’ve been trying to use ThumbnailTools::CacheThumbnail in my asset factory to assign a thumbnail, which as best as I can tell is how other systems assign thumbnails, including ContentBrowserUtils::CaptureThumbnailFromViewport. Unfortunately the thumbnail preview is still blank, and upon tracing through the code I see at some point the editor is assigning an empty thumbnail even though one has already been assigned.

Can anyone help with how I can assign an image as the thumbnail for an imported asset for my custom asset importer?

I eventually managed to get a thumbnail working last night. You need to implement a ThumbnailRenderer class that knows how to render your thumbnail and draw it to a Canvas object, and register it in your module as handling your custom type. Drawing on the canvas didn’t work as expected; most notably alpha didn’t seem to work properly.

I didn’t see this documented anywhere and looking through the code it seems several things create thumbnails without it. There should really be a tutorial or basic documentation on how to do this.

1 Like

For anyone wondering how it’s actually done in Unreal Engine 5, start by creating a custom renderer:

UCLASS(MinimalAPI)
class UMyThumbnailRenderer : public UThumbnailRenderer
{
	GENERATED_BODY()
public:
	// Begin UThumbnailRenderer Object
	YOUREDITOR_API virtual void GetThumbnailSize(UObject* Object, float Zoom, uint32& OutWidth, uint32& OutHeight) const override;
	YOUREDITOR_API virtual void Draw(UObject* Object, int32 X, int32 Y, uint32 Width, uint32 Height, FRenderTarget*, FCanvas* Canvas, bool bAdditionalViewFamily) override;
	// End UThumbnailRenderer Object
};

In your module initialization function, register it:

void FMyditorModule::StartupModule()
{
	UThumbnailManager::Get().RegisterCustomRenderer(UMyAsset::StaticClass(), UMyThumbnailRenderer::StaticClass());
}

void FMyEditorModule::ShutdownModule()
{
	if (FModuleManager::Get().IsModuleLoaded("AssetTools"))
	{
		UThumbnailManager::Get().UnregisterCustomRenderer(UMyThumbnailRenderer::StaticClass());
	}
}

For how to implement UMyThumbnailRenderer::Draw, you might want to look how it’s done for textures in the Engine.

For example, to draw a centered text, you can use the following code:

static void DrawTextOnCanvas(const TCHAR* Text, uint32 Width, uint32 Height, FCanvas* Canvas, float Scale = 1.f, FLinearColor Color = FLinearColor::White)
{
	int32 TextWidth = 0;
	int32 TextHeight = 0;
	StringSize(GEngine->GetLargeFont(), TextWidth, TextHeight, Text);
	
	FCanvasTextItem TextItem(FVector2D((Width - TextWidth * Scale) / 2., (Height - TextHeight * Scale) / 2.), FText::FromString(Text), GEngine->GetLargeFont(), Color);
	TextItem.EnableShadow(FLinearColor::Black);
	TextItem.Scale = FVector2D::UnitVector * Scale;
	TextItem.Draw(Canvas);
}
1 Like