Delete MCPAssets and the things that use it.
This commit is contained in:
@@ -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);
|
|
||||||
}
|
|
||||||
@@ -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"
|
||||||
|
|||||||
@@ -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]); }
|
|
||||||
};
|
|
||||||
Reference in New Issue
Block a user