FARFilter Exclusion Set not filtering classes

Hello,

So I’m having an issue with filtering classes with the asset registry FARFilter.

I want to exclude my object libraries from being included in the filter, but it is still including object libraries. The code compiles, and even prints the object library class to the log successfully.

First I’m creating the FARFilter and setting bRecursiveClasses to true because according to the docs you need to do this for the recursive classes exclusion set to work.

FARFilter AssetRegistryFilter;
AssetRegistryFilter.bRecursiveClasses = true;

Then I add the object library class as a filter. (The object library is passed into this function and is valid).

AssetRegistryFilter.RecursiveClassesExclusionSet.Add(ObjectLibrary->GetClass());

Then I print the object libray class to make sure it is finding the correct class.

UE_LOG(LogTemp, Warning, TEXT("class: %s"), *ObjectLibrary->GetClass()->GetFName().ToString());

But when I output all the found assets, the list still contains the object library.

AssetRegistryModule.Get().GetAssets(AssetRegistryFilter, FilteredAssetData);

As you can see the first log is the object library class, then rest is the filtered asset data which still contains object libraries. Any idea on what is going on?

Hi Steve SybrSyn,

Could you provide a more complete code example of how you’re attempting to search the asset registry? I am unable to reproduce this with a quick test that I wrote.

Hey, sure no problem. Thank you for your help, as I have been staring at this for days now and I am 100% positive this should be working, i have looked at engine examples and I do not see why it wouldn’t.

As a work around I have to instead iterate over the result with an if check and manually filter out the library, which I would rather just use the exclusion set if it worked.

Also I have checked everything by printing to the log, the bRecursiveClasses is being set to true, and the object library name is being inserted into the exclusion set as well.

Here is the complete function, it’s basically taking in an object library, gets its path and sub paths, and filtering the results of the items in the same directory. (Which is working great except its not filtering out the object library classes)

TArray<FPrimaryAssetId> UCoreLibraryManagerComponent::FilterByFloatRange(UObjectLibrary* ObjectLibrary, FInputRange FilterRange, FName FilterProperty)
{
	if (ObjectLibrary)
	{
		// Creates the asset registry module.
		FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>("AssetRegistry");
		IAssetRegistry& AssetRegistry = AssetRegistryModule.Get();

		// The asset registry filter.
		FARFilter AssetRegistryFilter;

		// Enable the filter to use exclusion sets.
		AssetRegistryFilter.bRecursiveClasses = true;

		// The object library path and all sub-paths found in the object library's path.
		TArray<FString> ObjectLibraryPaths;

		// The object library path (Top level).
		FString ParentPath = FPaths::GetPath(ObjectLibrary->GetPathName());
		// All recursive sub-paths in the object library's directory.
		AssetRegistry.GetSubPaths(ParentPath, ObjectLibraryPaths, true);
		ObjectLibraryPaths.Add(ParentPath);

		// Excludes the object library class from the filter (NOT WORKING)
		AssetRegistryFilter.RecursiveClassesExclusionSet.Add(ObjectLibrary->GetClass()->GetFName());

// Add all paths to the filter.
for (const FString& Path : ObjectLibraryPaths)
{
// Need to convert the path string to name.
AssetRegistryFilter.PackagePaths.Add(FName(*Path));
}

    		// Add property name to tag filter.
    		AssetRegistryFilter.TagsAndValues.Add(FilterProperty);
    
    		// The filtered asset data result.
    		TArray<FAssetData> FilteredAssetData;
    		// Applies the filter to the assets and stores the result into filtered asset data.
    		AssetRegistry.GetAssets(AssetRegistryFilter, FilteredAssetData);
    
    		// The filtered primary asset ids to return. 
    		TArray<FPrimaryAssetId> FilteredPrimaryAssetIDs;
    
    		// Loop through all the filtered asset data.
    		for (const FAssetData& Asset : FilteredAssetData)
    		{
    			// Filter out all the object libraries - because filter recursive classes exclusion set does not work.
    			if (Asset.AssetClass != ObjectLibrary->GetClass()->GetFName())
    			{
    				// Get the value of filter property.
    				uint8 PropertyValue = Asset.GetTagValueRef<uint8>(FilterProperty);
    				if (PropertyValue >= FilterRange.Min && PropertyValue <= FilterRange.Max)
    				{
    					// Gets the filtered asset id and adds it to the final filter array.
    					FilteredPrimaryAssetIDs.Add(Asset.GetPrimaryAssetId());
    				}
    			}
    		}
    
    		// Return the result.
    		return FilteredPrimaryAssetIDs;
    	}
    
    	// Error if an object library is not supplied.
    	UE_LOG(LogTemp, Warning, TEXT("No valid object library supplied!"))
    	return TArray<FPrimaryAssetId>();
    }

Also this is the complete function with my work around implemented near the end. (So this code would work and filter out the object libraries, just not the ideal way.)

Hi Steve,

Hmm… Yes, your code does look like it should be working. To clarify, though, the problem is that the filter is excluding items that directly inherit from ObjectLibrary's class but not Blueprints that inherit from that class or another, more derived class, correct?

No. The filter is not excluding Object Library classes. I want it to exclude the object library’s.

I am not using a custom object library class though, because when I create a custom c++ object library that inherits from object library, the engine will not compile anymore and throws a bunch of errors… So I’m using the default object library class. Which is fine, it would be nice to use a custom object library class but the engine won’t let me for some reason.

Basically I’m use the object library as a way to get the path the object library is in. Then when I have that path I can use that to automatically find and return all primary assets in the path and all sub paths. (This allows designers to select the object library they want an item from and apply filters to it.) This works great but it also finding and returning the object libraries themselves. Even when I properly exclude the object library class, the filter does not do anything.

Hi Steve,

I’ve done some more testing with this and the issue occurs with other classes as well. I’ve gone ahead and reported this as a bug. Once it is made available for public viewing, you can follow its progress on the issues site.

Awesome, thank you for your help!

Seems to work if ClassNames is populated with values.

Example:
AssetRegistryFilter.ClassNames.Add(UObject::StaticClass()->GetFName());

RecursiveClassesExclusionSet seems to only apply to filtering the ClassNames array.

Ahhh I see, that is something I did not do. I will have to go back and test this out, I did not know I had to add the class names like that, I found no engine examples doing that. Thank you Rex.Hill!