EM_Task/UnrealEd/Private/Subsystems/ImportSubsystem.cpp

173 lines
6.1 KiB
C++
Raw Permalink Normal View History

2026-02-13 16:18:33 +08:00
// Copyright Epic Games, Inc. All Rights Reserved.
#include "Subsystems/ImportSubsystem.h"
#include "Editor.h"
#include "AssetToolsModule.h"
#include "ObjectTools.h"
#include "FileHelpers.h"
#include "EditorReimportHandler.h"
#include "Misc/BlacklistNames.h"
class FImportFilesByPath: public IImportSubsystemTask
{
public:
FImportFilesByPath(const TArray<FString>& InFiles, const FString& InRootDestinationPath): Files(InFiles),
RootDestinationPath(InRootDestinationPath)
{
}
virtual void Run() override
{
TArray<FString> ImportFiles;
TMap<FString, UObject*> ReimportFiles;
FAssetToolsModule& AssetToolsModule = FModuleManager::Get().LoadModuleChecked<FAssetToolsModule>("AssetTools");
TArray<TPair<FString, FString>> FilesAndDestinations;
AssetToolsModule.Get().ExpandDirectories(Files, RootDestinationPath, FilesAndDestinations);
TArray<int32> ReImportIndexes;
for (int32 FileIdx = 0; FileIdx < FilesAndDestinations.Num(); ++FileIdx)
{
const FString& Filename = FilesAndDestinations[FileIdx].Key;
const FString& DestinationPath = FilesAndDestinations[FileIdx].Value;
FString Name = ObjectTools::SanitizeObjectName(FPaths::GetBaseFilename(Filename));
FString PackageName = ObjectTools::SanitizeInvalidChars(DestinationPath + TEXT("/") + Name, INVALID_LONGPACKAGE_CHARACTERS);
// We can not create assets that share the name of a map file in the same location
if (FEditorFileUtils::IsMapPackageAsset(PackageName))
{
// The error message will be log in the import process
ImportFiles.Add(Filename);
continue;
}
// Check if package exist in memory
UPackage* Pkg = FindPackage(nullptr, *PackageName);
bool IsPkgExist = Pkg != nullptr;
// check if package exist on file
if (!IsPkgExist && !FPackageName::DoesPackageExist(PackageName))
{
ImportFiles.Add(Filename);
continue;
}
if (Pkg == nullptr)
{
Pkg = CreatePackage(*PackageName);
if (Pkg == nullptr)
{
// Cannot create a package that don't exist on disk or in memory!!!
// The error message will be log in the import process
ImportFiles.Add(Filename);
continue;
}
}
// Make sure the destination package is loaded
Pkg->FullyLoad();
// Check for an existing object
UObject* ExistingObject = StaticFindObject(UObject::StaticClass(), Pkg, *Name);
if (ExistingObject != nullptr)
{
ReimportFiles.Add(Filename, ExistingObject);
ReImportIndexes.Add(FileIdx);
}
else
{
ImportFiles.Add(Filename);
}
}
// Reimport
for (auto kvp: ReimportFiles)
{
FReimportManager::Instance()->Reimport(kvp.Value, false, true, kvp.Key);
}
// Import
if (ImportFiles.Num() > 0)
{
// Remove it in reverse so the smaller index are still valid
for (int32 IndexToRemove = ReImportIndexes.Num() - 1; IndexToRemove >= 0; --IndexToRemove)
{
FilesAndDestinations.RemoveAt(ReImportIndexes[IndexToRemove]);
}
AssetToolsModule.Get().ImportAssets(ImportFiles, RootDestinationPath, nullptr, true, &FilesAndDestinations);
}
}
private:
TArray<FString> Files;
FString RootDestinationPath;
};
UImportSubsystem::UImportSubsystem()
: UEditorSubsystem()
{
}
void UImportSubsystem::Initialize(FSubsystemCollectionBase& Collection)
{
}
void UImportSubsystem::Deinitialize()
{
}
void UImportSubsystem::ImportNextTick(const TArray<FString>& Files, const FString& DestinationPath)
{
FAssetToolsModule& AssetToolsModule = FModuleManager::LoadModuleChecked<FAssetToolsModule>("AssetTools");
if (!AssetToolsModule.Get().GetWritableFolderBlacklist()->PassesStartsWithFilter(DestinationPath))
{
AssetToolsModule.Get().NotifyBlockedByWritableFolderFilter();
return;
}
PendingTasks.Enqueue(MakeShared<FImportFilesByPath>(Files, DestinationPath));
GEditor->GetTimerManager()->SetTimerForNextTick(this, &UImportSubsystem::HandleNextTick);
}
void UImportSubsystem::HandleNextTick()
{
if (!PendingTasks.IsEmpty())
{
TSharedPtr<IImportSubsystemTask> Task;
while (PendingTasks.Dequeue(Task))
{
if (Task.IsValid())
{
Task->Run();
}
}
}
}
PRAGMA_DISABLE_DEPRECATION_WARNINGS
void UImportSubsystem::BroadcastAssetPreImport(UFactory* InFactory, UClass* InClass, UObject* InParent, const FName& Name, const TCHAR* Type)
{
FEditorDelegates::OnAssetPreImport.Broadcast(InFactory, InClass, InParent, Name, Type);
OnAssetPreImport.Broadcast(InFactory, InClass, InParent, Name, Type);
OnAssetPreImport_BP.Broadcast(InFactory, InClass, InParent, Name, FString(Type));
}
void UImportSubsystem::BroadcastAssetPostImport(UFactory* InFactory, UObject* InCreatedObject)
{
FEditorDelegates::OnAssetPostImport.Broadcast(InFactory, InCreatedObject);
OnAssetPostImport.Broadcast(InFactory, InCreatedObject);
OnAssetPostImport_BP.Broadcast(InFactory, InCreatedObject);
}
void UImportSubsystem::BroadcastAssetReimport(UObject* InCreatedObject)
{
FEditorDelegates::OnAssetReimport.Broadcast(InCreatedObject);
OnAssetReimport.Broadcast(InCreatedObject);
OnAssetReimport_BP.Broadcast(InCreatedObject);
}
void UImportSubsystem::BroadcastAssetPostLODImport(UObject* InObject, int32 inLODIndex)
{
OnAssetPostLODImport.Broadcast(InObject, inLODIndex);
OnAssetPostLODImport_BP.Broadcast(InObject, inLODIndex);
}
PRAGMA_ENABLE_DEPRECATION_WARNINGS