Files
integration/Plugins/BlueprintMCP/Source/BlueprintMCP/Public/MCPAssetFinder.h
2026-03-08 21:28:47 -04:00

154 lines
4.4 KiB
C++

#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 can be stored in variables, or in string builders,
// or in json trees. This example tells it to put error
// messages into a string variable:
//
// FString ErrorMessage;
// Assets.Errors(ErrorMessage)
//
// 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).Errors(ErrMsg).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& Errors(MCPErrorCallback InCB);
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;
MCPErrorCallback ErrorCB = MCPErrorCallback(nullptr);
};
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]); }
};