feat: asset usage audit plugin
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>
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
// NextGenium 2026. Asset Usage Audit.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
|
||||
/**
|
||||
* One /Game path literal found in a text file, with enough context to check it by hand.
|
||||
*/
|
||||
struct FIndirectReference
|
||||
{
|
||||
/** Package name the literal resolved to, e.g. /Game/Space/Core/GameModes/BP_FirstPersonGameMode. */
|
||||
FName PackageName;
|
||||
|
||||
/** Absolute path of the file the literal was found in. */
|
||||
FString SourceFile;
|
||||
|
||||
/** 1-based line number. */
|
||||
int32 LineNumber = 0;
|
||||
|
||||
/** True when the hit came from Config/, false when from Source/. */
|
||||
bool bFromConfig = false;
|
||||
|
||||
FString ToProvenanceString() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* Finds asset paths referenced from text rather than from a package.
|
||||
*
|
||||
* This exists because of a concrete, measured failure mode on this project: Config/DefaultEngine.ini
|
||||
* names BP_FirstPersonGameMode, BP_MenuSystemGameInstance, RefinedMenuMap and Gyms_Geoda as plain
|
||||
* strings. No asset references them, so the Asset Registry reports zero referencers and a naive
|
||||
* audit calls the project's GameMode unused.
|
||||
*
|
||||
* It is a mitigation, not a solution. It cannot see a path assembled at runtime by concatenation,
|
||||
* an OpenLevel(FName) call, or an FMOD event path - those stay Unknown, deliberately.
|
||||
*/
|
||||
class ASSETUSAGEAUDITCORE_API FIndirectReferenceScanner
|
||||
{
|
||||
public:
|
||||
struct FOptions
|
||||
{
|
||||
/** Absolute directories to scan. Defaults to <Project>/Config and <Project>/Source. */
|
||||
TArray<FString> Directories;
|
||||
|
||||
/** File extensions to read, lowercase, with the dot. */
|
||||
TArray<FString> Extensions = { TEXT(".ini"), TEXT(".cpp"), TEXT(".h"), TEXT(".cs") };
|
||||
|
||||
/** Skip files larger than this; a multi-megabyte generated file is never a reference site. */
|
||||
int64 MaxFileSizeBytes = 8 * 1024 * 1024;
|
||||
};
|
||||
|
||||
/** Scan and return every distinct package path found, with provenance. */
|
||||
static TArray<FIndirectReference> Scan(const FOptions& Options);
|
||||
|
||||
/** Default options: <Project>/Config and <Project>/Source. */
|
||||
static FOptions MakeDefaultOptions();
|
||||
|
||||
/**
|
||||
* Extract /Game path literals from one line of text.
|
||||
*
|
||||
* Exposed for testing: the trailing-_C strip and the delimiter set are where this goes wrong.
|
||||
* "/Game/X/BP_Y.BP_Y_C" and "/Game/X/BP_Y" must both yield the package /Game/X/BP_Y.
|
||||
*/
|
||||
static void ExtractGamePathsFromLine(FStringView Line, TArray<FString>& OutPackageNames);
|
||||
};
|
||||
Reference in New Issue
Block a user