113 lines
3.1 KiB
C++
113 lines
3.1 KiB
C++
#pragma once
|
|
|
|
#include "CoreMinimal.h"
|
|
#include "WingServer.h"
|
|
#include "WingHandler.h"
|
|
#include "WingUtils.h"
|
|
#include "UObject/UObjectIterator.h"
|
|
#include "Class_Search.generated.h"
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// ---------------------------------------------------------------------------
|
|
// ---------------------------------------------------------------------------
|
|
|
|
// ============================================================
|
|
// HandleListClasses — discover available UClasses
|
|
// ============================================================
|
|
|
|
UCLASS()
|
|
class UWing_Class_Search : public UObject, public IWingHandler
|
|
{
|
|
GENERATED_BODY()
|
|
|
|
public:
|
|
UPROPERTY(meta=(Optional, Description="Substring filter for class names"))
|
|
FString Query;
|
|
|
|
UPROPERTY(meta=(Optional, Description="Parent class name to restrict results to subclasses"))
|
|
FString ParentClass;
|
|
|
|
UPROPERTY(meta=(Optional, Description="Maximum number of results to return (1-500, default 100)"))
|
|
int32 Limit = 100;
|
|
|
|
virtual FString GetDescription() const override
|
|
{
|
|
return TEXT("Search for available UClasses by name substring and/or parent class. "
|
|
"Returns class names, parent class, package, and flags.");
|
|
}
|
|
|
|
virtual void Handle() override
|
|
{
|
|
Limit = FMath::Clamp(Limit, 1, 500);
|
|
|
|
UClass* ParentClassObj = nullptr;
|
|
if (!ParentClass.IsEmpty())
|
|
{
|
|
for (TObjectIterator<UClass> It; It; ++It)
|
|
{
|
|
if (WingUtils::Identifies(ParentClass, *It))
|
|
{
|
|
ParentClassObj = *It;
|
|
break;
|
|
}
|
|
}
|
|
if (!ParentClassObj)
|
|
{
|
|
UWingServer::Printf(TEXT("Error: Parent class '%s' not found\n"), *ParentClass);
|
|
return;
|
|
}
|
|
}
|
|
|
|
TArray<UClass*> Matches;
|
|
int32 TotalMatched = 0;
|
|
|
|
for (TObjectIterator<UClass> It; It; ++It)
|
|
{
|
|
UClass* Class = *It;
|
|
if (!Class) continue;
|
|
if (Class->HasAnyClassFlags(CLASS_Deprecated | CLASS_NewerVersionExists)) continue;
|
|
if (ParentClassObj && !Class->IsChildOf(ParentClassObj)) continue;
|
|
|
|
FString ClassName = WingUtils::FormatName(Class);
|
|
if (!Query.IsEmpty() && !ClassName.Contains(Query, ESearchCase::IgnoreCase)) continue;
|
|
|
|
TotalMatched++;
|
|
if (Matches.Num() < Limit)
|
|
{
|
|
Matches.Add(Class);
|
|
}
|
|
}
|
|
|
|
UWingServer::Printf(TEXT("Found %d classes"), TotalMatched);
|
|
if (TotalMatched > Limit)
|
|
{
|
|
UWingServer::Printf(TEXT(" (showing %d)"), Limit);
|
|
}
|
|
UWingServer::Print(TEXT("\n"));
|
|
|
|
for (UClass* Class : Matches)
|
|
{
|
|
UWingServer::Printf(TEXT(" %s"), *WingUtils::FormatName(Class));
|
|
|
|
// Flags
|
|
TStringBuilder<64> Flags;
|
|
if (Class->HasAnyClassFlags(CLASS_Abstract)) Flags.Append(TEXT(" Abstract"));
|
|
if (Class->HasAnyClassFlags(CLASS_Interface)) Flags.Append(TEXT(" Interface"));
|
|
if (Class->HasAnyClassFlags(CLASS_MinimalAPI)) Flags.Append(TEXT(" MinimalAPI"));
|
|
if (Class->ClassGeneratedBy) Flags.Append(TEXT(" Blueprint"));
|
|
if (Flags.Len() > 0)
|
|
{
|
|
UWingServer::Printf(TEXT(" [%s]"), Flags.ToString() + 1); // skip leading space
|
|
}
|
|
|
|
if (Class->GetSuperClass())
|
|
{
|
|
UWingServer::Printf(TEXT(" : %s"), *WingUtils::FormatName(Class->GetSuperClass()));
|
|
}
|
|
|
|
UWingServer::Print(TEXT("\n"));
|
|
}
|
|
}
|
|
};
|