Delete MCPAssets and the things that use it.

This commit is contained in:
2026-03-17 23:29:24 -04:00
parent 26de2351db
commit 42fb0a8453
5 changed files with 0 additions and 316 deletions

View File

@@ -1,169 +0,0 @@
#include "MCPAssets.h"
#include "MCPServer.h"
#include "Engine/Blueprint.h"
#include "Engine/World.h"
#include "Engine/Level.h"
#include "Engine/LevelScriptBlueprint.h"
#include "Materials/Material.h"
#include "MCPUtils.h"
#include "AssetRegistry/AssetRegistryModule.h"
#include "AssetRegistry/IAssetRegistry.h"
// ============================================================
// MCPAssetsBase
// ============================================================
MCPAssetsBase::MCPAssetsBase(UClass* InTargetClass)
: TargetClass(InTargetClass)
{
Scans.Add(InTargetClass);
}
MCPAssetsBase& MCPAssetsBase::Exact(const FString& InName)
{
MatchName = InName;
bExactMatch = true;
bPatternHasSlash = MatchName.Contains(TEXT("/"));
return *this;
}
MCPAssetsBase& MCPAssetsBase::Substring(const FString& InFilter)
{
MatchName = InFilter;
bExactMatch = false;
bPatternHasSlash = MatchName.Contains(TEXT("/"));
return *this;
}
MCPAssetsBase& MCPAssetsBase::NoDerived()
{
bNoDerived = true;
return *this;
}
MCPAssetsBase& MCPAssetsBase::AllContent()
{
bAllContent = true;
return *this;
}
bool MCPAssetsBase::Info()
{
// In theory, there's no reason a person couldn't load/info
// more than once, to obtain updates. Might as well allow it.
AssetResults.Empty();
UObjectResults.Empty();
// Query the asset registry
IAssetRegistry& AR = FModuleManager::LoadModuleChecked<FAssetRegistryModule>("AssetRegistry").Get();
TArray<FAssetData> Candidates;
AR.GetAssets(ConfigureFilter(), Candidates);
for (const FAssetData &Data : Candidates)
{
if (AssetMatches(Data)) AssetResults.Add(Data);
if (bErrorIfAny && (AssetResults.Num() > 0))
{
SetError(FString::Printf(TEXT("%s '%s' already exists."), *TargetClass->GetName(), *AssetResults[0].PackageName.ToString()));
return false;
}
if (bErrorIfTwo && (AssetResults.Num() > 1))
{
SetError(FString::Printf(
TEXT("Ambiguous %s name '%s' — matches '%s' and '%s'. Use the full package path to disambiguate."),
*TargetClass->GetName(), *MatchName, *AssetResults[0].PackageName.ToString(), *AssetResults[1].PackageName.ToString()));
return false;
}
if (AssetResults.Num() >= MaxResults) break;
}
// Check error conditions on the result count
if (bErrorIfNone && AssetResults.IsEmpty())
{
SetError(FString::Printf(TEXT("%s '%s' not found."), *TargetClass->GetName(), *MatchName));
return false;
}
return true;
}
bool MCPAssetsBase::Load()
{
if (!Info()) return false;
TArray<FAssetData> AssetsToLoad;
Swap(AssetsToLoad, AssetResults);
for (const FAssetData &Asset : AssetsToLoad)
{
UObject *Obj = TryLoadAsset(Asset);
if (!Obj) continue;
// If this is a material open in the editor, use the editor's transient copy.
if (UMaterial* Mat = Cast<UMaterial>(Obj))
Obj = MCPUtils::ReplaceMaterialWithTransientCopy(Mat);
AssetResults.Add(Asset);
UObjectResults.Add(Obj);
}
if (bErrorIfNone && AssetResults.IsEmpty())
{
SetError(FString::Printf(TEXT("%s '%s' exists but cannot be loaded."), *TargetClass->GetName(),
*AssetsToLoad[0].PackageName.ToString()));
return false;
}
return true;
}
FARFilter MCPAssetsBase::ConfigureFilter()
{
FARFilter Filter;
for (UClass* C : Scans) Filter.ClassPaths.Add(C->GetClassPathName());
Filter.bRecursiveClasses = !bNoDerived;
if (!bAllContent)
{
Filter.PackagePaths.Add(FName(TEXT("/Game")));
Filter.bRecursivePaths = true;
}
return Filter;
}
bool MCPAssetsBase::AssetMatches(const FAssetData &Asset)
{
if (bExactMatch)
{
FString Name = bPatternHasSlash ? Asset.PackageName.ToString() : Asset.AssetName.ToString();
return Name.Equals(MatchName, ESearchCase::IgnoreCase);
}
else
{
return Asset.AssetName.ToString().Contains(MatchName, ESearchCase::IgnoreCase) ||
Asset.PackageName.ToString().Contains(MatchName, ESearchCase::IgnoreCase);
}
}
UObject *MCPAssetsBase::TryLoadAsset(const FAssetData &Asset)
{
UObject* Obj = Asset.GetAsset();
if (Obj == nullptr) return nullptr;
if (Obj->IsA(TargetClass)) return Obj;
if (TargetClass->IsChildOf(UBlueprint::StaticClass()) &&
ULevelScriptBlueprint::StaticClass()->IsChildOf(TargetClass))
{
UWorld* World = Cast<UWorld>(Obj);
if (World && World->PersistentLevel)
{
ULevelScriptBlueprint* LevelBP = World->PersistentLevel->GetLevelScriptBlueprint(true);
if (LevelBP) return LevelBP;
}
}
return nullptr;
}
void MCPAssetsBase::SetError(const FString &Msg)
{
AssetResults.Empty();
UObjectResults.Empty();
UMCPServer::Printf(TEXT("ERROR: %s\n"), *Msg);
}

View File

@@ -3,7 +3,6 @@
#include "MCPJson.h" #include "MCPJson.h"
#include "LogCapture.h" #include "LogCapture.h"
#include "MCPUtils.h" #include "MCPUtils.h"
#include "MCPAssets.h"
#include "UObject/StrongObjectPtr.h" #include "UObject/StrongObjectPtr.h"
#include "Materials/MaterialExpression.h" #include "Materials/MaterialExpression.h"
#include "AssetRegistry/AssetRegistryModule.h" #include "AssetRegistry/AssetRegistryModule.h"

View File

@@ -1,146 +0,0 @@
#pragma once
#include "CoreMinimal.h"
#include "AssetRegistry/AssetData.h"
#include "MCPUtils.h"
#include "Engine/Blueprint.h"
#include "Engine/LevelScriptBlueprint.h"
#include "Engine/World.h"
struct FARFilter;
////////////////////////////////////////////////////////////
//
// MCPAssets - search for assets.
//
//
// Construct an object of class MCPAssets like this:
//
// MCPAssets<UBlueprint> Assets;
//
// The UBlueprint template parameter means that this example
// Assets loader is capable of storing pointers to
// UBlueprint.
//
// It also means that by default, it will scan
// all UBlueprint assets. You can narrow that:
//
// Assets.NoScans();
// Assets.Scan<UAnimBlueprint>();
// Assets.Scan<ULuprexBlueprint>();
//
// To get string matching, call either 'Exact' or
// 'Substring'. If you don't call either of these, there's
// no string filter. If the string you pass in contains a
// slash, then the search is by asset-path, otherwise, by
// asset-name:
//
// Assets.Substring(TEXT("MyAsset"));
//
// By default, the asset finder limits itself to assets in
// the /Game folder. You can expand that:
//
// Assets.AllContent();
//
// You can specify that you don't want to see derived
// classes:
//
// Assets.NoDerived()
//
// You can specify a limit on the number of results
// returned:
//
// Assets.Limit(100)
//
// You can specify what constitutes an error condition. If
// the asset finder detects an error, then it will report
// it:
//
// Assets.ENone() - it's an error if nothing is found
// Assets.EAny() - it's an error if anything is found
// Assets.ETwo() - it's an error if two or more are found
//
// Errors are reported via UMCPServer::Printf.
//
// Once the Assets object is configured, it's time to scan
// the assets. Use 'Info' if you just want to see
// FAssetData. Use 'Load' if you want to load the assets
// into memory. Both of these functions return true if
// there were no errors, or false if there was one.
//
// bool ok = Assets.Load();
//
// Once you've scanned the assets, you can examine the
// results using the following methods. The objects array
// will be empty if you called 'Info' instead of 'Load':
//
// const TArray<FAssetData>& AllData();
// const FAssetData& OneData();
// const TArray<UBlueprint*> Objects();
// UBlueprint* Object();
//
//
// MCPAssets configuration methods can be chained:
//
// Assets.Limit(100).ENone().ETwo();
//
////////////////////////////////////////////////////////////
class MCPAssetsBase
{
public:
MCPAssetsBase& NoScans() { Scans.Empty(); return *this; }
MCPAssetsBase& Scan(UClass* Class) { Scans.Add(Class); return *this; }
template<class T> MCPAssetsBase& Scan() { return Scan(T::StaticClass()); }
MCPAssetsBase& Exact(const FString& InName);
MCPAssetsBase& Substring(const FString& InFilter);
MCPAssetsBase& Limit(int32 Count) { MaxResults = Count; return *this; }
MCPAssetsBase& NoDerived();
MCPAssetsBase& AllContent();
MCPAssetsBase& EAny() { bErrorIfAny = true; return *this; }
MCPAssetsBase& ENone() { bErrorIfNone = true; return *this; }
MCPAssetsBase& ETwo() { bErrorIfTwo = true; return *this; }
bool Load();
bool Info();
const TArray<FAssetData>& AllData() const { return AssetResults; }
const FAssetData& OneData() const { return AssetResults[0]; }
private:
FARFilter ConfigureFilter();
bool AssetMatches(const FAssetData &Data);
UObject *TryLoadAsset(const FAssetData &Asset);
void SetError(const FString &Msg);
protected:
MCPAssetsBase(UClass* InTargetClass);
UClass* TargetClass;
TSet<UClass*> Scans;
TArray<FAssetData> AssetResults;
TArray<UObject*> UObjectResults;
FString MatchName;
bool bExactMatch = false;
bool bPatternHasSlash = false;
bool bNoDerived = false;
bool bAllContent = false;
bool bErrorIfAny = false;
bool bErrorIfNone = false;
bool bErrorIfTwo = false;
int32 MaxResults = 50;
};
template<class T>
class MCPAssets : public MCPAssetsBase
{
public:
MCPAssets() : MCPAssetsBase(T::StaticClass()) {}
TArrayView<T* const> Objects() const
{
return TArrayView<T* const>(reinterpret_cast<T* const*>(UObjectResults.GetData()), UObjectResults.Num());
}
T* Object() const { return UObjectResults.IsEmpty() ? nullptr : static_cast<T*>(UObjectResults[0]); }
};