diff --git a/Engine/Source/Runtime/AssetRegistry/Private/AssetRegistry.cpp b/Engine/Source/Runtime/AssetRegistry/Private/AssetRegistry.cpp index 7593988c9..36f3cd5a9 100644 --- a/Engine/Source/Runtime/AssetRegistry/Private/AssetRegistry.cpp +++ b/Engine/Source/Runtime/AssetRegistry/Private/AssetRegistry.cpp @@ -773,6 +773,14 @@ bool UAssetRegistryImpl::EnumerateAssets(const FARCompiledFilter& InFilter, TFun return; } +#if WITH_EDITOR + // Skip classes that report themselves as assets but that the editor AssetRegistry is currently not counting as assets + if (ShouldSkipAsset(Obj->GetClass()->GetFName(), InMemoryPackage->GetPackageFlags())) + { + return; + } +#endif + // Package name const FName PackageName = InMemoryPackage->GetFName(); @@ -2117,9 +2125,17 @@ void UAssetRegistryImpl::AssetSearchDataGathered(const double TickStartTime, TBa // Add the found assets while (AssetResults.Num() > 0) { - FAssetData*& BackgroundResult = AssetResults.Pop(); + // Delete or take ownership of the BackgroundResult; it was originally new'd by an FPackageReader + TUniquePtr BackgroundResult(AssetResults.Pop()); + CA_ASSUME(BackgroundResult.Get() != nullptr); - CA_ASSUME(BackgroundResult); +#if WITH_EDITOR + // Skip Assets that we filter out + if (ShouldSkipAsset(BackgroundResult->AssetClass, BackgroundResult->PackageFlags)) + { + continue; + } +#endif // Try to update any asset data that may already exist FAssetData* AssetData = State.CachedAssetsByObjectPath.FindRef(BackgroundResult->ObjectPath); @@ -2128,20 +2144,16 @@ void UAssetRegistryImpl::AssetSearchDataGathered(const double TickStartTime, TBa if (AssetData) { // If this ensure fires then we've somehow processed the same result more than once, and that should never happen - if (ensure(AssetData != BackgroundResult)) + if (ensure(AssetData != BackgroundResult.Get())) { // The asset exists in the cache, update it UpdateAssetData(AssetData, *BackgroundResult); - - // Delete the result that was originally created by an FPackageReader - delete BackgroundResult; - BackgroundResult = nullptr; } } else { // The asset isn't in the cache yet, add it and notify subscribers - AddAssetData(BackgroundResult); + AddAssetData(BackgroundResult.Release()); } // Populate the path tree @@ -2661,8 +2673,29 @@ void UAssetRegistryImpl::OnDirectoryChanged(const TArray& FileC ScanModifiedAssetFiles(ModifiedFiles); } +bool UAssetRegistryImpl::ShouldSkipAsset(FName AssetClass, uint32 PackageFlags) const +{ + // We do not yet support having UBlueprintGeneratedClasses be assets when the UBlueprint is also + // an asset; the content browser does not handle the multiple assets correctly and displays this + // class asset as if it is in a separate package. Revisit when we have removed the UBlueprint as an asset + // or when we support multiple assets. + static FName NAME_BlueprintGeneratedClass = TEXT("BlueprintGeneratedClass"); + bool bIsCooked = (PackageFlags & PKG_FilterEditorOnly) != 0; + if (!bIsCooked && AssetClass == NAME_BlueprintGeneratedClass) + { + return true; + } + return false; +} + void UAssetRegistryImpl::OnAssetLoaded(UObject *AssetLoaded) { + UPackage* Package = AssetLoaded->GetPackage(); + if (Package && ShouldSkipAsset(AssetLoaded->GetClass()->GetFName(), Package->GetPackageFlags())) + { + return; + } + LoadedAssetsToProcess.Add(AssetLoaded); } diff --git a/Engine/Source/Runtime/AssetRegistry/Private/AssetRegistry.h b/Engine/Source/Runtime/AssetRegistry/Private/AssetRegistry.h index cec717ed7..d3fff4882 100644 --- a/Engine/Source/Runtime/AssetRegistry/Private/AssetRegistry.h +++ b/Engine/Source/Runtime/AssetRegistry/Private/AssetRegistry.h @@ -213,6 +213,9 @@ class UAssetRegistryImpl : public UObject, public IAssetRegistry /** Called when a file in a content directory changes on disk */ void OnDirectoryChanged(const TArray& Files); + /** Called to check whether we should filter out assets of the given class and packageflags from the editor's AssetRegistry */ + bool ShouldSkipAsset(FName AssetClass, uint32 PackageFlags) const; + /** Called when an asset is loaded, it will possibly update the cache */ void OnAssetLoaded(UObject *AssetLoaded); diff --git a/Engine/Source/Runtime/AssetRegistry/Private/AssetRegistryState.cpp b/Engine/Source/Runtime/AssetRegistry/Private/AssetRegistryState.cpp index ecad60839..dda1f8c44 100644 --- a/Engine/Source/Runtime/AssetRegistry/Private/AssetRegistryState.cpp +++ b/Engine/Source/Runtime/AssetRegistry/Private/AssetRegistryState.cpp @@ -1492,11 +1492,18 @@ void FAssetRegistryState::AddAssetData(FAssetData* AssetData) { NumAssets++; + FAssetData*& ExistingByObjectPath = CachedAssetsByObjectPath.FindOrAdd(AssetData->ObjectPath); + if (ExistingByObjectPath) + { + UE_LOG(LogAssetRegistry, Error, TEXT("AddAssetData called with ObjectPath %s which already exists. ") + TEXT("This will overwrite and leak the existing AssetData."), *AssetData->ObjectPath.ToString()); + } + ExistingByObjectPath = AssetData; + TArray& PackageAssets = CachedAssetsByPackageName.FindOrAdd(AssetData->PackageName); TArray& PathAssets = CachedAssetsByPath.FindOrAdd(AssetData->PackagePath); TArray& ClassAssets = CachedAssetsByClass.FindOrAdd(AssetData->AssetClass); - CachedAssetsByObjectPath.Add(AssetData->ObjectPath, AssetData); PackageAssets.Add(AssetData); PathAssets.Add(AssetData); ClassAssets.Add(AssetData); diff --git a/Engine/Source/Runtime/Engine/Classes/Engine/BlueprintGeneratedClass.h b/Engine/Source/Runtime/Engine/Classes/Engine/BlueprintGeneratedClass.h index 986005847..d443f8bf2 100644 --- a/Engine/Source/Runtime/Engine/Classes/Engine/BlueprintGeneratedClass.h +++ b/Engine/Source/Runtime/Engine/Classes/Engine/BlueprintGeneratedClass.h @@ -746,6 +746,8 @@ class ENGINE_API UBlueprintGeneratedClass : public UClass #if WITH_EDITOR virtual UClass* RegenerateClass(UClass* ClassToRegenerate, UObject* PreviousCDO) override; #endif //WITH_EDITOR + virtual bool IsAsset() const override; + // End UObject interface // UClass interface diff --git a/Engine/Source/Runtime/Engine/Private/BlueprintGeneratedClass.cpp b/Engine/Source/Runtime/Engine/Private/BlueprintGeneratedClass.cpp index 1f8b94bc6..614cf4308 100644 --- a/Engine/Source/Runtime/Engine/Private/BlueprintGeneratedClass.cpp +++ b/Engine/Source/Runtime/Engine/Private/BlueprintGeneratedClass.cpp @@ -162,8 +162,11 @@ void UBlueprintGeneratedClass::PostLoad() FPrimaryAssetId UBlueprintGeneratedClass::GetPrimaryAssetId() const { FPrimaryAssetId AssetId; - if (!ensure(ClassDefaultObject)) + if (!ClassDefaultObject) { + // All UBlueprintGeneratedClass objects should have a pointer to their generated ClassDefaultObject, except for the + // CDO itself of the UBlueprintGeneratedClass class. + verify(HasAnyFlags(RF_ClassDefaultObject)); return AssetId; } @@ -1583,6 +1586,14 @@ UClass* UBlueprintGeneratedClass::RegenerateClass(UClass* ClassToRegenerate, UOb } #endif +bool UBlueprintGeneratedClass::IsAsset() const +{ + // UClass::IsAsset returns false; override that to return true for BlueprintGeneratedClasses, + // but only if the instance satisfies the regular definition of an asset (RF_Public, not transient, etc) + // and only if it is the active BPGC matching the Blueprint + return UObject::IsAsset() && !HasAnyClassFlags(CLASS_NewerVersionExists); +} + void UBlueprintGeneratedClass::Link(FArchive& Ar, bool bRelinkExistingProperties) { Super::Link(Ar, bRelinkExistingProperties);