diff --git a/Plugins/BlueprintMCP/Source/BlueprintMCP/HalfBaked/Blueprint_Search.h b/Plugins/BlueprintMCP/Deprecated/Blueprint_Search.h similarity index 100% rename from Plugins/BlueprintMCP/Source/BlueprintMCP/HalfBaked/Blueprint_Search.h rename to Plugins/BlueprintMCP/Deprecated/Blueprint_Search.h diff --git a/Plugins/BlueprintMCP/Source/BlueprintMCP/HalfBaked/Blueprint_SearchContents.h b/Plugins/BlueprintMCP/Deprecated/Blueprint_SearchContents.h similarity index 100% rename from Plugins/BlueprintMCP/Source/BlueprintMCP/HalfBaked/Blueprint_SearchContents.h rename to Plugins/BlueprintMCP/Deprecated/Blueprint_SearchContents.h diff --git a/Plugins/BlueprintMCP/Source/BlueprintMCP/Private/MCPAssets.cpp b/Plugins/BlueprintMCP/Source/BlueprintMCP/Private/MCPAssets.cpp deleted file mode 100644 index aff8ac5e..00000000 --- a/Plugins/BlueprintMCP/Source/BlueprintMCP/Private/MCPAssets.cpp +++ /dev/null @@ -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("AssetRegistry").Get(); - - TArray 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 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(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(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); -} diff --git a/Plugins/BlueprintMCP/Source/BlueprintMCP/Private/MCPServer.cpp b/Plugins/BlueprintMCP/Source/BlueprintMCP/Private/MCPServer.cpp index bb84da4e..0d75098c 100644 --- a/Plugins/BlueprintMCP/Source/BlueprintMCP/Private/MCPServer.cpp +++ b/Plugins/BlueprintMCP/Source/BlueprintMCP/Private/MCPServer.cpp @@ -3,7 +3,6 @@ #include "MCPJson.h" #include "LogCapture.h" #include "MCPUtils.h" -#include "MCPAssets.h" #include "UObject/StrongObjectPtr.h" #include "Materials/MaterialExpression.h" #include "AssetRegistry/AssetRegistryModule.h" diff --git a/Plugins/BlueprintMCP/Source/BlueprintMCP/Public/MCPAssets.h b/Plugins/BlueprintMCP/Source/BlueprintMCP/Public/MCPAssets.h deleted file mode 100644 index a7094fce..00000000 --- a/Plugins/BlueprintMCP/Source/BlueprintMCP/Public/MCPAssets.h +++ /dev/null @@ -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 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(); -// Assets.Scan(); -// -// 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& AllData(); -// const FAssetData& OneData(); -// const TArray 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 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& 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 Scans; - TArray AssetResults; - TArray 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 MCPAssets : public MCPAssetsBase -{ -public: - MCPAssets() : MCPAssetsBase(T::StaticClass()) {} - - TArrayView Objects() const - { - return TArrayView(reinterpret_cast(UObjectResults.GetData()), UObjectResults.Num()); - } - T* Object() const { return UObjectResults.IsEmpty() ? nullptr : static_cast(UObjectResults[0]); } -};