Skip to content

Instantly share code, notes, and snippets.

@Aaron1178
Last active May 14, 2023 11:16
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Aaron1178/d97fda37d6baffa660efd0bd0ca6399b to your computer and use it in GitHub Desktop.
Save Aaron1178/d97fda37d6baffa660efd0bd0ca6399b to your computer and use it in GitHub Desktop.
Use the Asset Registry to Register WidgetBlueprints as Primary Asset Types of their respective base class.
void UMyAssetManager::StartInitialLoading()
{
Super::StartInitialLoading();
UE_LOG(LogMyAssetManager, Log, TEXT("Initializing MyAssetManager"))
if ( !bHasScannedForWidgetBlueprints )
{
/** Scan for and Register Widget Blueprints with the Asset Manager*/
Get().RegisterWidgetBlueprintsPrimaryAssets<UMyBaseUUserWidgetClass>();
}
}
/** Note: Class names etc have been changed for public use. */
template <class T> void UMyAssetManager::RegisterWidgetBlueprintsPrimaryAssets( const FString Path /*= "/Game"*/, const bool bShowAssetManagerDump /*= false*/ )
{
FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>(FName("AssetRegistry"));
IAssetRegistry& AssetRegistry = AssetRegistryModule.Get();
if ( Path.IsEmpty() )
{
UE_LOG(LogMyAssetManager, Warning, TEXT("Path parameter is empty. Please specify a content directory"));
return;
}
TArray<FString> ContentPaths;
ContentPaths.Add(Path);
/** Scan ContenPaths recursivley */
AssetRegistry.ScanPathsSynchronous(ContentPaths, true);
TSet<FName> DerivedNames;
{
TArray<FName> BaseNames; //The base Class Names
BaseNames.Add(T::StaticClass()->GetFName());
TSet<FName> Excluded;
/** Get a list of class names derived from BaseNames */
AssetRegistry.GetDerivedClassNames(BaseNames, Excluded, DerivedNames);
}
/** Create a FARFilter to search for WidgetBlueprint type classes */
FARFilter Filter;
Filter.ClassNames.Add(FName("WidgetBlueprint"));
Filter.bRecursivePaths = true;
Filter.bRecursiveClasses = true;
TArray<FAssetData> AssetList;
/** Get a list of FAssetData the matches the search criteria of the FARFilter */
AssetRegistry.GetAssets(Filter, AssetList);
for ( FAssetData Asset : AssetList )
{
/** Get the the class this blueprint generates (this is stored as a full path e.g "WidgetBlueprintGeneratedClass'/Game/Assets/NewWidgetBlueprint.NewWidgetBlueprint_C'") */
FAssetTagValueRef GeneratedClassPathPtr = Asset.TagsAndValues.FindTag(TEXT("GeneratedClass"));
if ( GeneratedClassPathPtr.IsSet() )
{
/** Convert path to just the name part e.g "/Game/Assets/NewWidgetBlueprint.NewWidgetBlueprint_C" */
const FString ClassObjectPath = FPackageName::ExportTextPathToObjectPath(GeneratedClassPathPtr.AsString());
const FString ClassName = FPackageName::ObjectPathToObjectName(ClassObjectPath);
/** Check if this class is in the derived set */
if ( !DerivedNames.Contains(*ClassName) )
{
continue;
}
/** The SoftObjectPath to our class */
FSoftObjectPath SoftPath(ClassObjectPath);
/** Try to cast the UObject returned from SoftPath.TryLoad() to UWidgetBlueprintGeneratedClass */
if ( UWidgetBlueprintGeneratedClass* Cls = Cast<UWidgetBlueprintGeneratedClass>(SoftPath.TryLoad()) )
{
/** Cast the UWidgetBlueprintGeneratedClass' default object to UMyBaseUUserWidget */
if ( T* UIAsset = Cast<T>(Cls->GetDefaultObject()) )
{
/** Register the specific WidgetBlueprint Asset as a PrimaryAsset using the UMyBaseUUserWidget->GetPrimaryAssetId() function.
* This is neccessary as Asset->GetPrimaryAssetId() will not return the proper PrimaryAssetId as it will auto generate to
* "MyBaseUUserWidget:AssetName".
*/
Get().RegisterSpecificPrimaryAsset(UIAsset->GetPrimaryAssetId(), Asset);
}
}
}
}
/** Optional debug information*/
if ( bShowAssetManagerDump )
{
UE_LOG(LogMyAssetManager, Log, TEXT("Dumping Asset Manager Info"));
Get().DumpAssetRegistryInfo();
Get().DumpAssetTypeSummary();
Get().DumpLoadedAssetState();
}
bHasScannedForWidgetBlueprints = true;
}
template <class T> T* UMyAssetManager::GetWidgetFromAssetData( const FAssetData AssetData, UGameInstance* GameInstance) const
{
FAssetTagValueRef GenClassTag = AssetData.TagsAndValues.FindTag(FName("GeneratedClass"));
/** Check and see if the "GeneratedClass" tag was found */
if ( GenClassTag.IsSet() )
{
const FString ObjPath = FPackageName::ExportTextPathToObjectPath(GenClassTag.AsString());
const FSoftObjectPath SoftObjectPath(GenClassTag.AsString());
/** Try and load the class and cast it to UWidgetBlueprintGeneratedClass */
if ( UWidgetBlueprintGeneratedClass* BpClass = Cast<UWidgetBlueprintGeneratedClass>(SoftObjectPath.TryLoad()) )
{
/** Try to CreateWidget of type T with a valid UGameInstance and the UWidgetBlueprintGenerated class above */
if( T* Object = CreateWidget<T>(GameInstance, BpClass) )
{
/** If our Object widget is valid, we return it */
return Object;
}
}
}
return nullptr;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment