b7f5343a73
Editor tool for the LA and 3D departments: which assets each level uses, which are used nowhere, and export of a chosen set. Three modules. AssetUsageAuditCore holds the whole analysis and links no UI and no editor-only asset pipeline, so it stays runnable from a commandlet; AssetUsageAuditEditor holds the Slate panel and everything that needs UnrealEd or AssetTools; AssetUsageAuditTests holds 152 specs. Load-bearing decisions, each of which produces a wrong answer if undone: - Dependency queries are always Package + NoRequirements, never Hard. The map-to-external-actor edges the OFPA gatherer emits carry Game|Build without Hard, so a Hard query drops all 16117 external actor packages in this project. There is deliberately no Hard constant in the code. - Crossing into another map is allowed only from a level or its external actor package. Without that rule WP_Main reported 18136 assets, of which 9994 belonged to L_MainLevel, reached through the GameMode. - The verdict has five states, never a bool. The registry cannot see FMOD events, DataTable rows or string-built paths; those are Unknown, and the tool never proposes a deletion. - Copying .uasset files does not preserve references - they are stored as full package paths. Only the Migrate layout produces something Unreal can open; the others write a manifest so the graph can be rebuilt. Co-Authored-By: Claude Code <noreply@anthropic.com>
84 lines
3.1 KiB
C++
84 lines
3.1 KiB
C++
// NextGenium 2026. Asset Usage Audit.
|
|
|
|
#pragma once
|
|
|
|
#include "CoreMinimal.h"
|
|
#include "AssetUsageAuditTypes.h"
|
|
#include "AssetUsageExporter.h"
|
|
|
|
class IAssetRegistry;
|
|
|
|
/**
|
|
* The JSON written beside a reference-breaking export.
|
|
*
|
|
* Why it exists: references inside a .uasset are stored as full package names, so a copied file
|
|
* only resolves when it sits at exactly that package path in the destination. The Flat and
|
|
* FolderPerAsset layouts deliberately do not put it there - they arrange files for a person to read
|
|
* and hand around - so the reference graph is lost the moment the files leave the project.
|
|
*
|
|
* The manifest records that graph next to the files, so a later import can rebuild it rather than
|
|
* guess. It is written from what the exporter actually wrote, never from what it intended to write:
|
|
* the two differ exactly when the collision policy renamed something, which is the case a manifest
|
|
* has to get right.
|
|
*
|
|
* Migrate needs none of this - the engine preserves the paths itself - and asking for a manifest
|
|
* there is treated as a caller mistake rather than silently producing a misleading file.
|
|
*/
|
|
namespace AssetExportManifest
|
|
{
|
|
/** Bumped when the schema changes in a way a reader must notice. */
|
|
inline constexpr int32 SchemaVersion = 1;
|
|
|
|
/** Manifest filename, written into the export root. */
|
|
inline const TCHAR* FileName = TEXT("AssetUsageAudit.manifest.json");
|
|
|
|
struct FOptions
|
|
{
|
|
/** Export root. The manifest is written here and paths are relative to it. */
|
|
FString TargetDirectory;
|
|
|
|
/** Recorded so a reader knows why the paths look the way they do. */
|
|
EExportLayout Layout = EExportLayout::Flat;
|
|
|
|
EExportCollisionPolicy CollisionPolicy = EExportCollisionPolicy::Index;
|
|
|
|
/**
|
|
* Packages the user ticked, as opposed to those pulled in as dependencies.
|
|
*
|
|
* Kept apart because an importer needs to know which assets were the point and which came
|
|
* along to make them work - "restore what I exported" and "restore everything in this
|
|
* folder" are different requests.
|
|
*/
|
|
TSet<FName> SeedPackages;
|
|
};
|
|
|
|
struct ASSETUSAGEAUDITCORE_API FResult
|
|
{
|
|
bool bSuccess = false;
|
|
|
|
/** Absolute path of the manifest, empty on failure. */
|
|
FString FilePath;
|
|
|
|
int32 EntriesWritten = 0;
|
|
|
|
/** Dependency edges recorded across all entries. */
|
|
int32 EdgesRecorded = 0;
|
|
|
|
FString ErrorMessage;
|
|
};
|
|
|
|
/**
|
|
* Write the manifest.
|
|
*
|
|
* @param WrittenFiles From FAssetUsageExporter::FResult::WrittenFiles, which requires the
|
|
* exporter to have been run with bRecordWrittenFiles. An empty array is a
|
|
* failure rather than an empty manifest: it almost always means the flag
|
|
* was forgotten, and an empty manifest beside a full folder is worse than
|
|
* no manifest at all.
|
|
*/
|
|
ASSETUSAGEAUDITCORE_API FResult Write(
|
|
IAssetRegistry& Registry,
|
|
const TArray<FAssetUsageExporter::FWrittenFile>& WrittenFiles,
|
|
const FOptions& Options);
|
|
}
|