You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
#jira UE-161932 #rb julien.stjean #preflight https://horde.devtools.epicgames.com/job/6324e773f258fccf98de78cf [CL 22064625 by robert millar in ue5-main branch]
208 lines
7.5 KiB
C++
208 lines
7.5 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "CollectionAssetRegistryBridge.h"
|
|
|
|
#include "AssetRegistry/AssetData.h"
|
|
#include "AssetRegistry/AssetRegistryModule.h"
|
|
#include "AssetRegistry/IAssetRegistry.h"
|
|
#include "CollectionManagerModule.h"
|
|
#include "CollectionManagerTypes.h"
|
|
#include "Containers/Set.h"
|
|
#include "ContentBrowserLog.h"
|
|
#include "Delegates/Delegate.h"
|
|
#include "HAL/Platform.h"
|
|
#include "ICollectionManager.h"
|
|
#include "Logging/LogCategory.h"
|
|
#include "Logging/LogMacros.h"
|
|
#include "Misc/AssertionMacros.h"
|
|
#include "Misc/PackageName.h"
|
|
#include "Modules/ModuleManager.h"
|
|
#include "Trace/Detail/Channel.h"
|
|
#include "UObject/Class.h"
|
|
#include "UObject/ConstructorHelpers.h"
|
|
#include "UObject/LinkerLoad.h"
|
|
#include "UObject/NameTypes.h"
|
|
#include "UObject/UObjectGlobals.h"
|
|
#include "UObject/UnrealNames.h"
|
|
|
|
#define LOCTEXT_NAMESPACE "ContentBrowser"
|
|
|
|
/** The collection manager doesn't know how to follow redirectors, this class provides it with that knowledge */
|
|
class FCollectionRedirectorFollower : public ICollectionRedirectorFollower
|
|
{
|
|
public:
|
|
FCollectionRedirectorFollower()
|
|
: AssetRegistryModule(FModuleManager::LoadModuleChecked<FAssetRegistryModule>(TEXT("AssetRegistry")))
|
|
{
|
|
}
|
|
|
|
virtual bool FixupObject(const FSoftObjectPath& InObjectPath, FSoftObjectPath& OutNewObjectPath) override
|
|
{
|
|
OutNewObjectPath = FSoftObjectPath();
|
|
|
|
FString InObjectPathString = InObjectPath.ToString();
|
|
if (!InObjectPathString.StartsWith(TEXT("/")))
|
|
{
|
|
if (!GIsSavingPackage)
|
|
{
|
|
FTopLevelAssetPath FullPath = UClass::TryConvertShortTypeNameToPathName(UClass::StaticClass(), InObjectPathString);
|
|
if (FullPath.IsValid())
|
|
{
|
|
FString ClassPathStr = FullPath.ToString();
|
|
const FString NewClassName = FLinkerLoad::FindNewPathNameForClass(ClassPathStr, false);
|
|
if (!NewClassName.IsEmpty())
|
|
{
|
|
check(FPackageName::IsValidObjectPath(NewClassName));
|
|
// Our new class name might be lacking the path, so try and find it so we can use the full path in the collection
|
|
UClass* FoundClass = FindObject<UClass>(nullptr, *NewClassName);
|
|
if (FoundClass)
|
|
{
|
|
OutNewObjectPath = *FoundClass->GetPathName();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (InObjectPathString.StartsWith(TEXT("/Script/")))
|
|
{
|
|
// We can't use FindObject while we're saving
|
|
if (!GIsSavingPackage)
|
|
{
|
|
const FString ClassPathStr = InObjectPath.ToString();
|
|
check(FPackageName::IsValidObjectPath(ClassPathStr));
|
|
UClass* FoundClass = FindObject<UClass>(nullptr, *ClassPathStr);
|
|
if (!FoundClass)
|
|
{
|
|
// Use the linker to search for class name redirects (from the loaded ActiveClassRedirects)
|
|
const FString NewClassName = FLinkerLoad::FindNewPathNameForClass(ClassPathStr, false);
|
|
|
|
if (!NewClassName.IsEmpty())
|
|
{
|
|
check(FPackageName::IsValidObjectPath(NewClassName));
|
|
// Our new class name might be lacking the path, so try and find it so we can use the full path in the collection
|
|
FoundClass = FindObject<UClass>(nullptr, *NewClassName);
|
|
if (FoundClass)
|
|
{
|
|
OutNewObjectPath = *FoundClass->GetPathName();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Keep track of visted redirectors in case we loop.
|
|
TSet<FSoftObjectPath> VisitedRedirectors;
|
|
|
|
// Use the asset registry to avoid loading the object
|
|
PRAGMA_DISABLE_DEPRECATION_WARNINGS
|
|
FAssetData ObjectAssetData = AssetRegistryModule.Get().GetAssetByObjectPath(InObjectPath, true);
|
|
PRAGMA_ENABLE_DEPRECATION_WARNINGS
|
|
while (ObjectAssetData.IsValid() && ObjectAssetData.IsRedirector())
|
|
{
|
|
// Check to see if we've already seen this path before, it's possible we might have found a redirector loop.
|
|
if ( VisitedRedirectors.Contains(ObjectAssetData.ToSoftObjectPath()) )
|
|
{
|
|
UE_LOG(LogContentBrowser, Error, TEXT("Redirector Loop Found!"));
|
|
for ( const FSoftObjectPath& Redirector : VisitedRedirectors )
|
|
{
|
|
UE_LOG(LogContentBrowser, Error, TEXT("Redirector: %s"), *Redirector.ToString());
|
|
}
|
|
|
|
ObjectAssetData = FAssetData();
|
|
break;
|
|
}
|
|
|
|
VisitedRedirectors.Add(ObjectAssetData.ToSoftObjectPath());
|
|
|
|
// Get the destination object from the meta-data rather than load the redirector object, as
|
|
// loading a redirector will also load the object it points to, which could cause a large hitch
|
|
FString DestinationObjectPath;
|
|
if (ObjectAssetData.GetTagValue("DestinationObject", DestinationObjectPath))
|
|
{
|
|
ConstructorHelpers::StripObjectClass(DestinationObjectPath);
|
|
ObjectAssetData = AssetRegistryModule.Get().GetAssetByObjectPath(FSoftObjectPath(DestinationObjectPath));
|
|
}
|
|
else
|
|
{
|
|
ObjectAssetData = FAssetData();
|
|
}
|
|
}
|
|
|
|
PRAGMA_DISABLE_DEPRECATION_WARNINGS
|
|
OutNewObjectPath = ObjectAssetData.ObjectPath;
|
|
PRAGMA_ENABLE_DEPRECATION_WARNINGS
|
|
}
|
|
|
|
return OutNewObjectPath.IsValid() && InObjectPath != OutNewObjectPath;
|
|
}
|
|
|
|
private:
|
|
FAssetRegistryModule& AssetRegistryModule;
|
|
};
|
|
|
|
FCollectionAssetRegistryBridge::FCollectionAssetRegistryBridge()
|
|
{
|
|
// Load the asset registry module to listen for updates
|
|
FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>(TEXT("AssetRegistry"));
|
|
AssetRegistryModule.Get().OnAssetRemoved().AddRaw(this, &FCollectionAssetRegistryBridge::OnAssetRemoved);
|
|
AssetRegistryModule.Get().OnAssetRenamed().AddRaw(this, &FCollectionAssetRegistryBridge::OnAssetRenamed);
|
|
|
|
if (AssetRegistryModule.Get().IsLoadingAssets())
|
|
{
|
|
AssetRegistryModule.Get().OnFilesLoaded().AddRaw(this, &FCollectionAssetRegistryBridge::OnAssetRegistryLoadComplete);
|
|
}
|
|
else
|
|
{
|
|
OnAssetRegistryLoadComplete();
|
|
}
|
|
}
|
|
|
|
FCollectionAssetRegistryBridge::~FCollectionAssetRegistryBridge()
|
|
{
|
|
// Load the asset registry module to unregister delegates
|
|
if (FModuleManager::Get().IsModuleLoaded("AssetRegistry"))
|
|
{
|
|
FAssetRegistryModule& AssetRegistryModule = FModuleManager::GetModuleChecked<FAssetRegistryModule>(TEXT("AssetRegistry"));
|
|
AssetRegistryModule.Get().OnAssetRemoved().RemoveAll(this);
|
|
AssetRegistryModule.Get().OnAssetRenamed().RemoveAll(this);
|
|
AssetRegistryModule.Get().OnFilesLoaded().RemoveAll(this);
|
|
}
|
|
}
|
|
|
|
void FCollectionAssetRegistryBridge::OnAssetRegistryLoadComplete()
|
|
{
|
|
FCollectionManagerModule& CollectionManagerModule = FCollectionManagerModule::GetModule();
|
|
|
|
// We've found all the assets, let the collections manager fix up its references now so that it doesn't reference any redirectors
|
|
FCollectionRedirectorFollower RedirectorFollower;
|
|
CollectionManagerModule.Get().HandleFixupRedirectors(RedirectorFollower);
|
|
}
|
|
|
|
void FCollectionAssetRegistryBridge::OnAssetRenamed(const FAssetData& AssetData, const FString& OldObjectPath)
|
|
{
|
|
FCollectionManagerModule& CollectionManagerModule = FCollectionManagerModule::GetModule();
|
|
|
|
// Notify the collections manager that an asset has been renamed
|
|
CollectionManagerModule.Get().HandleObjectRenamed(FSoftObjectPath(OldObjectPath), AssetData.GetSoftObjectPath());
|
|
}
|
|
|
|
void FCollectionAssetRegistryBridge::OnAssetRemoved(const FAssetData& AssetData)
|
|
{
|
|
FCollectionManagerModule& CollectionManagerModule = FCollectionManagerModule::GetModule();
|
|
|
|
if (AssetData.IsRedirector())
|
|
{
|
|
// Notify the collections manager that a redirector has been removed
|
|
// This will attempt to re-save any collections that still have a reference to this redirector in their on-disk collection data
|
|
CollectionManagerModule.Get().HandleRedirectorDeleted(AssetData.GetSoftObjectPath());
|
|
}
|
|
else
|
|
{
|
|
// Notify the collections manager that an asset has been removed
|
|
CollectionManagerModule.Get().HandleObjectDeleted(AssetData.GetSoftObjectPath());
|
|
}
|
|
}
|
|
|
|
#undef LOCTEXT_NAMESPACE
|