Find All Assets of Some Type

I’m trying to accomplish something that I thought would be fairly simple, but, I cannot figure out how to do it. So, I’ve got a folder full of MediaTextures and I want to populate a list at runtime of those MediaTextures. I don’t want to use a Data Asset because that’s a bit inconvenient, every time another MediaTexture is added, it would have to manually be added to the data asset/cvs/excel. So, here’s one sort of thing that I’ve tried:

void UMediaLoadFunctions::FindMediaTextures(TArray <UMediaTexture*> &Textures, TArray<FString> &FileNames) {
	TArray<FString> FoundFileNames;
	IFileManager& FileMgr = IFileManager::Get();
	FString FilePath(FPaths::Combine(*FPaths::GameDir(), TEXT("/Content/Movies")));
	FileMgr.FindFiles(FoundFileNames,*FilePath, nullptr);
	FString FilePath2(FPaths::Combine(*FPaths::GameDir(), TEXT("Content/Movies")));
	for (int i = 0; i < FoundFileNames.Num(); i++) {
		FString FilePath3 = FString("/Game/Movies/") + FoundFileNames[i];
		FStringAssetReference AssetRef(FilePath3);
		UObject * FoundMedia = AssetRef.TryLoad();
		if (FoundMedia != NULL) {
			FileNames.Add(FilePath3);
		}
		else {
			FileNames.Add(FString("Couldn't add ") + FoundFileNames[i]);
		}
	}

}

I’ve also tried using LoadObject(…) and StaticLoadObject(…) I’ve played around with using the full path to the directory (which I don’t think would even work in a packaged project) and I’ve tried using the paths that work in some other situations: “/Game/Movies” And, I simply cannot load these objects. I’ve spent too much time on this, what is the proper way to accomplish this?

I’ve also checked out this answerhub post, and this wiki entry, and haven’t gleaned an answer from either.

Well, when choosing tags, asset registry gave me a hint. Here’s a nasty bruteforce solution: (In case anyone needs it or would like to give me some feedback)

	FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>("AssetRegistry");
	TArray<FAssetData> AssetData;
	AssetRegistryModule.Get().GetAssetsByClass(FName("MediaTexture"), AssetData);
	for (int i = 0; i < AssetData.Num(); i++) {
		UMediaTexture* FoundMedia = Cast<UMediaTexture>(AssetData[i].GetAsset());
		if (FoundMedia != NULL) {
			FileNames.Add(AssetData[i].GetFullName());
			Textures.Add(FoundMedia);
		}
	}

}
3 Likes

Here is a templated version of the code in skyler’s comment:

template<typename T>
void GetObjectsOfClass(TArray<T*>& OutArray)
{
	FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>("AssetRegistry");
	TArray<FAssetData> AssetData;
	AssetRegistryModule.Get().GetAssetsByClass(T::StaticClass()->GetFName(), AssetData);
	for (int i = 0; i < AssetData.Num(); i++) {
		T* Object = Cast<T>(AssetData[i].GetAsset());
		OutArray.Add(Object);
	}
}

Use it like this:

TArray<UAnimSequence*> AnimSequences;
GetObjectsOfClass<UAnimSequence>(AnimSequences);
5 Likes

Worth replying to, in 5.0 and up, the GetFName will no longer work. The new code will look like this:

template<typename T>
void GetObjectsOfClass(TArray<T*>& OutArray)
{
	FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>("AssetRegistry");
	TArray<FAssetData> AssetData;
	AssetRegistryModule.Get().GetAssetsByClass(FTopLevelAssetPath(T::StaticClass()->GetPathName()), AssetData);
	for (int i = 0; i < AssetData.Num(); i++) {
		T* Object = Cast<T>(AssetData[i].GetAsset());
		OutArray.Add(Object);
	}
}