EM_Task/UnrealEd/Private/Cooker/MPCookSideEffect.h
Boshuang Zhao 5144a49c9b add
2026-02-13 16:18:33 +08:00

95 lines
2.9 KiB
C++

#pragma once
#include "CoreMinimal.h"
#include "AssetRegistry/AssetData.h"
#include "Misc/CookSideEffectCollector.h"
namespace UE
{
namespace Cook
{
/**
* @struct FCookAssetData
* @brief Represents the asset registry information for a single asset within a package.
*/
struct FCookAssetData
{
FName AssetClass;
uint32 PackageFlags = 0;
TMap<FName, FString> Tags;
friend FArchive& operator<<(FArchive& Ar, FCookAssetData& Data)
{
Ar << Data.AssetClass;
Ar << Data.PackageFlags;
Ar << Data.Tags;
return Ar;
}
/** * Equality operator to compare asset data across processes.
* Necessary for Director to identify if the same asset's side effects are being reported.
*/
friend bool operator==(const FCookAssetData& A, const FCookAssetData& B)
{
if (A.AssetClass != B.AssetClass || A.Tags.Num() != B.Tags.Num())
{
return false;
}
for (const auto& TagPair: A.Tags)
{
const FString* BValue = B.Tags.Find(TagPair.Key);
if (!BValue || *BValue != TagPair.Value)
{
return false;
}
}
return true;
}
friend bool operator!=(const FCookAssetData& A, const FCookAssetData& B)
{
return !(A == B);
}
};
/**
* @class FMPCookSideEffectCollector
* @brief A thread-local singleton used to collect side-effect data (EDL, AssetRegistry) during a UPackage::Save operation.
*
* This avoids the need to modify the engine's SavePackage function signatures. The worker's save logic should
* call BeginPackage() before saving, and EndPackage() afterwards. The low-level functions like
* FEDLCookChecker::AddExport can then access the collector via Get() to get the current context and populate the data.
*/
class FCookWorkerClient;
struct FPackageData;
struct FMPCookSideEffectCollectorData
{
FCriticalSection CookSideEffectsLock;
FCriticalSection AssetPackageDataLock;
FCriticalSection AssetRegistryDataLock;
FCookSideEffects CookSideEffects;
TMap<FName, TArray<FCookAssetData>> AssetRegistryDataMap;
TMap<FName, TArray<FAssetPackageData>> AssetPackageDataMap;
void UniqueToCookSideEffects(FCookSideEffects& To);
};
class FMPCookSideEffectCollector: public ICookSideEffectCollector
{
public:
FMPCookSideEffectCollector() = default;
void AddExport(UObject* Export) override;
void AddImport(UObject* Import, UPackage* ImportingPackage) override;
void AddArc(UObject* DepObject, bool bDepIsSerialize, UObject* Export, bool bExportIsSerialize) override;
void RecordAssetTag(const ITargetPlatform* TargetPlatform, FName AssetPath, FName AssetClass, FName TagName, const FString& TagValue);
static void SetCookWorkerClient(FCookWorkerClient* InCookWorkerClient);
static ICookSideEffectCollector* NewCookSideEffectCollector();
private:
static FCookWorkerClient* CookWorkerClient;
};
} // namespace Cook
} // namespace UE