Files
AssetUsageAudit/Source/AssetUsageAuditEditor/Public/AssetUsageAuditLibrary.h
T
Admin 72bf94d142 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>
2026-09-03 17:07:59 +07:00

62 lines
2.4 KiB
C++

// NextGenium 2026. Asset Usage Audit.
#pragma once
#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "AssetUsageAuditLibrary.generated.h"
/**
* Blueprint and Python entry points for the audit.
*
* Phase 1 uses these as the only way to run the analysis, before the Slate panel exists. They
* remain useful afterwards: a TA can script a one-off audit from an Editor Utility Widget without
* touching the main tool, and the same calls drive the Python bridge.
*
* These are thin wrappers. All logic lives in AssetUsageAuditCore so that the panel, these
* functions and a future commandlet cannot drift apart.
*/
UCLASS()
class ASSETUSAGEAUDITEDITOR_API UAssetUsageAuditLibrary : public UBlueprintFunctionLibrary
{
GENERATED_BODY()
public:
/**
* Run a full audit and write JSON + CSV reports.
*
* @param LevelPackageNames Levels to analyse, e.g. "/Game/Space/Maps/WP_Main". Empty means all.
* @param OutputDirectory Destination. Empty uses the configured default.
* @param OutReportPath Absolute path of the JSON report on success.
* @return true when both reports were written.
*/
UFUNCTION(BlueprintCallable, Category = "Asset Usage Audit", meta = (AutoCreateRefTerm = "LevelPackageNames"))
static bool RunAudit(const TArray<FString>& LevelPackageNames, const FString& OutputDirectory, FString& OutReportPath);
/**
* Assets reachable from one level, resolved transitively through Blueprints and other assets.
*
* This is the question the tool exists to answer, exposed on its own for scripting.
*/
UFUNCTION(BlueprintCallable, Category = "Asset Usage Audit")
static TArray<FString> GetAssetsUsedOnLevel(const FString& LevelPackageName);
/**
* Levels that use the given asset.
*
* Includes both a sublevel and its parent map when the asset sits in a sublevel, because the
* parent's traversal reaches through ULevelStreaming::WorldAsset.
*/
UFUNCTION(BlueprintCallable, Category = "Asset Usage Audit")
static TArray<FString> GetLevelsUsingAsset(const FString& AssetPackageName);
/**
* Time a full sweep and log the breakdown.
*
* Exists to answer the open question in the plan: whether an in-memory graph cache is needed
* at all. Measure before adding one.
*/
UFUNCTION(BlueprintCallable, Category = "Asset Usage Audit")
static float MeasureFullSweepSeconds();
};