How to add custom asset extension (or a virtual asset)?

How can I add “virtual assets” to content browser?

For example, I have a file in content browser with extension .css, how do I tell the content browser about it?
How to display the icon and the name of asset in Editor WITHOUT creating respective .uasset file (this is important).

I know that Content Browser supports uassets and umaps. And I know that assets are shown when they are deserialized and the engine extracts all the information.

I need a solution without compiling the entire engine.

I wrote something, assets appear, but are not deleted if I delete .css files.

FDelegateHandle FCustomAssetManager::WatcherHandle = FDelegateHandle();

void FCustomAssetManager::Initialize()
{
	WatchDirectory = FPaths::ProjectContentDir();
	
	FDirectoryWatcherModule& DirectoryWatcher = FModuleManager::LoadModuleChecked<FDirectoryWatcherModule>("DirectoryWatcher");
	DirectoryWatcher.Get()->RegisterDirectoryChangedCallback_Handle(
		WatchDirectory,
		IDirectoryWatcher::FDirectoryChanged::CreateRaw(this, &FCustomAssetManager::ScanForCSSFiles),
		FCustomAssetManager::WatcherHandle,
		IDirectoryWatcher::WatchOptions::IncludeDirectoryChanges
	);
}

void FCustomAssetManager::Shutdown()
{
	if (FModuleManager::Get().IsModuleLoaded("DirectoryWatcher"))
	{
		FDirectoryWatcherModule& DirectoryWatcher = FModuleManager::LoadModuleChecked<FDirectoryWatcherModule>("DirectoryWatcher");
		DirectoryWatcher.Get()->UnregisterDirectoryChangedCallback_Handle(WatchDirectory, OnDirectoryChangedHandle);
	}
}

void FCustomAssetManager::ScanForCSSFiles(const TArray<FFileChangeData> & Data)
{

	if (Data.Num() == 0)
		return;
	
	for (FFileChangeData File : Data)
	{

		if (FPaths::GetExtension(File.Filename) != "css")
			continue;
		
		FContentBrowserModule& ContentBrowserModule = FModuleManager::LoadModuleChecked<FContentBrowserModule>("ContentBrowser");
		IContentBrowserSingleton& ContentBrowserSingleton = ContentBrowserModule.Get();

		IAssetRegistry& AssetRegistry = FModuleManager::LoadModuleChecked<FAssetRegistryModule>("AssetRegistry").Get();
		
		FAssetData VirtualAsset(
			FName(FPaths::GetBaseFilename(File.Filename)),
			FName("/Game"),
			FName(FPaths::GetBaseFilename(File.Filename)),
			FName("CSS")
		);
	
		FAssetRegistryState AssetRegistryState = FAssetRegistryState();
		
		if (File.Action == FFileChangeData::FCA_Removed)
		{
			bool bDummy;
			AssetRegistryState.RemoveAssetData(&VirtualAsset, false, bDummy, bDummy);
			AssetRegistry.AppendState(AssetRegistryState);
		}
		else if (File.Action == FFileChangeData::FCA_Added)
		{
			AssetRegistryState.AddAssetData(&VirtualAsset);
			AssetRegistry.AppendState(AssetRegistryState);
		}
	}
}

image

1 Like