Handler registration overhaul
This commit is contained in:
@@ -20,7 +20,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_ActorComponent_Add : public UObject, public IWingHandler
|
||||
class UWing_ActorComponent_Add : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_ActorComponent_Remove : public UObject, public IWingHandler
|
||||
class UWing_ActorComponent_Remove : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_ActorComponent_Reparent : public UObject, public IWingHandler
|
||||
class UWing_ActorComponent_Reparent : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_Asset_Backup : public UObject, public IWingHandler
|
||||
class UWing_Asset_Backup : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_Asset_ContentBrowse : public UObject, public IWingHandler
|
||||
class UWing_Asset_ContentBrowse : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "WingServer.h"
|
||||
#include "WingHandler.h"
|
||||
#include "WingFactories.h"
|
||||
#include "Asset_Create.generated.h"
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// ---------------------------------------------------------------------------
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_Asset_Create : public UObject, public IWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY(meta=(Description="Full asset path for the new asset (e.g. '/Game/MyFolder/MyAsset')"))
|
||||
FString AssetPath;
|
||||
|
||||
UPROPERTY(meta=(Description="Factory type name from Asset_SearchTypes (e.g. 'Material', 'Blueprint')"))
|
||||
FString Factory;
|
||||
|
||||
UPROPERTY(meta=(Optional, Description="Factory configuration properties as key-value pairs"))
|
||||
FWingJsonObject Config;
|
||||
|
||||
virtual FString GetDescription() const override
|
||||
{
|
||||
return TEXT("Create a new asset using a factory. Use Asset_SearchTypes to find "
|
||||
"available factory types and their configurable properties.");
|
||||
}
|
||||
|
||||
virtual void Handle() override
|
||||
{
|
||||
UWingFactories::CreateAsset(AssetPath, Factory, Config);
|
||||
}
|
||||
};
|
||||
@@ -18,7 +18,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_Asset_Delete : public UObject, public IWingHandler
|
||||
class UWing_Asset_Delete : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_Asset_FindReferences : public UObject, public IWingHandler
|
||||
class UWing_Asset_FindReferences : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_Asset_Rename : public UObject, public IWingHandler
|
||||
class UWing_Asset_Rename : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_Asset_Restore : public UObject, public IWingHandler
|
||||
class UWing_Asset_Restore : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_Asset_Search : public UObject, public IWingHandler
|
||||
class UWing_Asset_Search : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "WingServer.h"
|
||||
#include "WingHandler.h"
|
||||
#include "WingFactories.h"
|
||||
#include "Asset_SearchTypes.generated.h"
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// ---------------------------------------------------------------------------
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_Asset_SearchTypes : public UObject, public IWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY(meta=(Description="Query string, can contain *"))
|
||||
FString Query;
|
||||
|
||||
UPROPERTY(meta=(Optional, Description="Maximum number of results (default 50)"))
|
||||
int32 MaxResults = 50;
|
||||
|
||||
virtual FString GetDescription() const override
|
||||
{
|
||||
return TEXT("Search for asset factory types that can be used with Asset_Create. "
|
||||
"Returns factory names and their configurable properties.");
|
||||
}
|
||||
|
||||
virtual void Handle() override
|
||||
{
|
||||
FString ExtQuery = TEXT("*") + Query + TEXT("*");
|
||||
const TArray<UWingFactories::Info>& All = UWingFactories::AllFactories();
|
||||
|
||||
int32 Count = 0;
|
||||
for (const UWingFactories::Info& Entry : All)
|
||||
{
|
||||
if (Count >= MaxResults) break;
|
||||
if (!Entry.CanCreateNew()) continue;
|
||||
if (!Entry.Name.MatchesWildcard(ExtQuery, ESearchCase::IgnoreCase)) continue;
|
||||
|
||||
UWingServer::Printf(TEXT("%s\n"), *Entry.Name);
|
||||
|
||||
for (const FName& Prop : Entry.Config)
|
||||
{
|
||||
UWingServer::Printf(TEXT(" %s\n"), *Prop.ToString());
|
||||
}
|
||||
|
||||
Count++;
|
||||
}
|
||||
|
||||
if (Count == 0)
|
||||
{
|
||||
UWingServer::Print(TEXT("No matching factory types found.\n"));
|
||||
}
|
||||
else if (Count >= MaxResults)
|
||||
{
|
||||
UWingServer::Printf(TEXT("WARNING: Reached limit of %d results. You may specify MaxResults.\n"), MaxResults);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -18,7 +18,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_BlueprintGraph_Create : public UObject, public IWingHandler
|
||||
class UWing_BlueprintGraph_Create : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_BlueprintGraph_Delete : public UObject, public IWingHandler
|
||||
class UWing_BlueprintGraph_Delete : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_Blueprint_AddInterface : public UObject, public IWingHandler
|
||||
class UWing_Blueprint_AddInterface : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_Blueprint_RemoveInterface : public UObject, public IWingHandler
|
||||
class UWing_Blueprint_RemoveInterface : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_Blueprint_Compile : public UObject, public IWingHandler
|
||||
class UWing_Blueprint_Compile : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_Blueprint_Create : public UObject, public IWingHandler
|
||||
class UWing_Blueprint_Create : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_Blueprint_Dump : public UObject, public IWingHandler
|
||||
class UWing_Blueprint_Dump : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_Blueprint_Reparent : public UObject, public IWingHandler
|
||||
class UWing_Blueprint_Reparent : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Factories/Factory.h"
|
||||
#include "WingServer.h"
|
||||
#include "WingHandler.h"
|
||||
#include "WingFactories.h"
|
||||
#include "WingProperty.h"
|
||||
#include "Create_UsingFactory.generated.h"
|
||||
|
||||
UCLASS()
|
||||
class UWing_Create_UsingFactory : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY(meta=(Description="Full asset path for the new asset (e.g. '/Game/MyFolder/MyAsset')"))
|
||||
FString AssetPath;
|
||||
|
||||
virtual FString GetDescription() const override
|
||||
{
|
||||
return TEXT("Create a new asset using a factory.");
|
||||
}
|
||||
|
||||
virtual void Register(UWingServer* Server) override
|
||||
{
|
||||
TArray<UClass*> FactoryClasses;
|
||||
GetDerivedClasses(UFactory::StaticClass(), FactoryClasses);
|
||||
|
||||
for (UClass* Class : FactoryClasses)
|
||||
{
|
||||
if (Class->HasAnyClassFlags(CLASS_Abstract)) continue;
|
||||
|
||||
UFactory* CDO = Class->GetDefaultObject<UFactory>();
|
||||
if (!CDO->CanCreateNew() || !CDO->ShouldShowInNewMenu()) continue;
|
||||
|
||||
TArray<FName> ConfigProps = FWingProperty::GetNames(Class, CPF_Edit);
|
||||
if (ConfigProps.Num() > 0) continue;
|
||||
|
||||
FString CommandName = FString::Printf(TEXT("Create_%s"), *UWingFactories::DeriveFactoryName(Class));
|
||||
Server->AddHandler(CommandName, GetClass(), Class, EWingHandlerKind::Create);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void Handle() override
|
||||
{
|
||||
UClass* FactoryClass = Cast<UClass>(ConfigurationObject);
|
||||
UFactory* Factory = NewObject<UFactory>(GetTransientPackage(), FactoryClass);
|
||||
UWingFactories::CreateAsset(AssetPath, Factory);
|
||||
}
|
||||
};
|
||||
@@ -13,7 +13,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_Editor_ListOpenAssets : public UObject, public IWingHandler
|
||||
class UWing_Editor_ListOpenAssets : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_Editor_OpenAsset : public UObject, public IWingHandler
|
||||
class UWing_Editor_OpenAsset : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_EventDispatcher_Create : public UObject, public IWingHandler
|
||||
class UWing_EventDispatcher_Create : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_EventDispatcher_Delete : public UObject, public IWingHandler
|
||||
class UWing_EventDispatcher_Delete : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_GraphNode_ChooseMenu : public UObject, public IWingHandler
|
||||
class UWing_GraphNode_ChooseMenu : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ struct FSpawnNodeEntry
|
||||
|
||||
|
||||
UCLASS()
|
||||
class UWing_GraphNode_Create : public UObject, public IWingHandler
|
||||
class UWing_GraphNode_Create : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_GraphNode_Delete : public UObject, public IWingHandler
|
||||
class UWing_GraphNode_Delete : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_GraphNode_Dump : public UObject, public IWingHandler
|
||||
class UWing_GraphNode_Dump : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_GraphNode_GetComment : public UObject, public IWingHandler
|
||||
class UWing_GraphNode_GetComment : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_GraphNode_Rename : public UObject, public IWingHandler
|
||||
class UWing_GraphNode_Rename : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_GraphNode_SearchTypes : public UObject, public IWingHandler
|
||||
class UWing_GraphNode_SearchTypes : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_GraphNode_SetComment : public UObject, public IWingHandler
|
||||
class UWing_GraphNode_SetComment : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ struct FSetNodeDefaultEntry
|
||||
|
||||
|
||||
UCLASS()
|
||||
class UWing_GraphNode_SetDefaults : public UObject, public IWingHandler
|
||||
class UWing_GraphNode_SetDefaults : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ struct FMoveNodeEntry
|
||||
|
||||
|
||||
UCLASS()
|
||||
class UWing_GraphNode_SetPositions : public UObject, public IWingHandler
|
||||
class UWing_GraphNode_SetPositions : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_GraphNode_ShowMenu : public UObject, public IWingHandler
|
||||
class UWing_GraphNode_ShowMenu : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ struct FConnectPinsEntry
|
||||
|
||||
|
||||
UCLASS()
|
||||
class UWing_GraphPin_Connect : public UObject, public IWingHandler
|
||||
class UWing_GraphPin_Connect : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ struct FDisconnectPinEntry
|
||||
|
||||
|
||||
UCLASS()
|
||||
class UWing_GraphPin_Disconnect : public UObject, public IWingHandler
|
||||
class UWing_GraphPin_Disconnect : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_Graph_Dump : public UObject, public IWingHandler
|
||||
class UWing_Graph_Dump : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_MaterialInstance_ClearParameter : public UObject, public IWingHandler
|
||||
class UWing_MaterialInstance_ClearParameter : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_MaterialInstance_Create : public UObject, public IWingHandler
|
||||
class UWing_MaterialInstance_Create : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_MaterialInstance_DumpParameters : public UObject, public IWingHandler
|
||||
class UWing_MaterialInstance_DumpParameters : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_MaterialInstance_SetParameter : public UObject, public IWingHandler
|
||||
class UWing_MaterialInstance_SetParameter : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_Material_Compile : public UObject, public IWingHandler
|
||||
class UWing_Material_Compile : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_Material_Create : public UObject, public IWingHandler
|
||||
class UWing_Material_Create : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_Material_DumpParameters : public UObject, public IWingHandler
|
||||
class UWing_Material_DumpParameters : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_Property_Dump : public UObject, public IWingHandler
|
||||
class UWing_Property_Dump : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_Property_Get : public UObject, public IWingHandler
|
||||
class UWing_Property_Get : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_Property_Set : public UObject, public IWingHandler
|
||||
class UWing_Property_Set : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include "ShowCommands.generated.h"
|
||||
|
||||
UCLASS()
|
||||
class UWing_ShowCommands : public UObject, public IWingHandler
|
||||
class UWing_ShowCommands : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
@@ -21,6 +21,9 @@ public:
|
||||
UPROPERTY(meta=(Optional, Description="If true, return full details including parameter types and descriptions"))
|
||||
bool Verbose = false;
|
||||
|
||||
UPROPERTY(meta=(Optional, Description="Kind of command: Normal, or Create"))
|
||||
EWingHandlerKind Kind = EWingHandlerKind::Normal;
|
||||
|
||||
virtual FString GetDescription() const override
|
||||
{
|
||||
return TEXT("List all available commands with their descriptions.");
|
||||
@@ -31,16 +34,15 @@ public:
|
||||
FString QueryLower = Query.ToLower();
|
||||
FString PrevGroup;
|
||||
|
||||
for (UClass* Class : WingUtils::CollectHandlerClasses())
|
||||
for (const FWingHandlerConfig& H : UWingServer::AllHandlers())
|
||||
{
|
||||
FString ToolName = WingUtils::GetHandlerName(Class);
|
||||
if (!ToolName.ToLower().Contains(QueryLower))
|
||||
continue;
|
||||
if (H.Kind != Kind) continue;
|
||||
if (!H.Name.ToLower().Contains(QueryLower)) continue;
|
||||
|
||||
// Blank line between groups
|
||||
if (!Verbose)
|
||||
{
|
||||
FString Group = WingUtils::GetHandlerGroup(Class);
|
||||
FString Group = WingUtils::GetHandlerGroup(H.Class.Get());
|
||||
if (Group != PrevGroup)
|
||||
{
|
||||
if (!PrevGroup.IsEmpty())
|
||||
@@ -51,12 +53,20 @@ public:
|
||||
|
||||
if (Verbose)
|
||||
{
|
||||
WingManual::PrintHandlerHelp(Class);
|
||||
WingManual::PrintHandlerHelp(H);
|
||||
}
|
||||
else
|
||||
{
|
||||
WingManual::PrintHandlerPrototype(Class);
|
||||
WingManual::PrintHandlerPrototype(H);
|
||||
}
|
||||
}
|
||||
if (Kind == EWingHandlerKind::Normal)
|
||||
{
|
||||
UWingServer::Printf(TEXT(
|
||||
"\n"
|
||||
"You can also use ShowCommands with Kind=Create to see\n"
|
||||
"commands that create new assets.\n"
|
||||
"\n"));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "WingServer.h"
|
||||
#include "WingHandler.h"
|
||||
#include "WingFactories.h"
|
||||
#include "SysInfo_Factories.generated.h"
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// ---------------------------------------------------------------------------
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_SysInfo_Factories : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
virtual FString GetDescription() const override
|
||||
{
|
||||
return TEXT("Sysinfo commands are intended for the human who "
|
||||
"is developing this plugin, they help him to understand. "
|
||||
"unreal's internals better.");
|
||||
}
|
||||
|
||||
virtual void Handle() override
|
||||
{
|
||||
const TArray<UWingFactories::Info>& All = UWingFactories::AllFactories();
|
||||
|
||||
for (int nparam = 0; nparam < 10; nparam++)
|
||||
{
|
||||
for (const UWingFactories::Info& Entry : All)
|
||||
{
|
||||
if (Entry.Config.Num() != nparam) continue;
|
||||
if (!Entry.CanCreateNew()) continue;
|
||||
UWingServer::Printf(TEXT("%s"), *Entry.Name);
|
||||
|
||||
for (const FName& Prop : Entry.Config)
|
||||
{
|
||||
UWingServer::Printf(TEXT(" PARAM: %s"), *Prop.ToString());
|
||||
}
|
||||
UWingServer::Printf(TEXT("\n"));
|
||||
}
|
||||
UWingServer::Printf(TEXT("\n"));
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -12,7 +12,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_Test_Sanitizer : public UObject, public IWingHandler
|
||||
class UWing_Test_Sanitizer : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_Test_Tokenizer : public UObject, public IWingHandler
|
||||
class UWing_Test_Tokenizer : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_Test_TypeToText : public UObject, public IWingHandler
|
||||
class UWing_Test_TypeToText : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_Test_Unsanitize : public UObject, public IWingHandler
|
||||
class UWing_Test_Unsanitize : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_TypeName_Search : public UObject, public IWingHandler
|
||||
class UWing_TypeName_Search : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include "UserManual.generated.h"
|
||||
|
||||
UCLASS()
|
||||
class UWing_UserManual : public UObject, public IWingHandler
|
||||
class UWing_UserManual : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_Variables_Create : public UObject, public IWingHandler
|
||||
class UWing_Variables_Create : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_Variables_Dump : public UObject, public IWingHandler
|
||||
class UWing_Variables_Dump : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_Variables_Modify : public UObject, public IWingHandler
|
||||
class UWing_Variables_Modify : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_Variables_Remove : public UObject, public IWingHandler
|
||||
class UWing_Variables_Remove : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_Widget_Create : public UObject, public IWingHandler
|
||||
class UWing_Widget_Create : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_Widget_Delete : public UObject, public IWingHandler
|
||||
class UWing_Widget_Delete : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_Widget_Reparent : public UObject, public IWingHandler
|
||||
class UWing_Widget_Reparent : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_Widget_SearchTypes : public UObject, public IWingHandler
|
||||
class UWing_Widget_SearchTypes : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include "Editor.h"
|
||||
#include "WingUtils.h"
|
||||
#include "WingProperty.h"
|
||||
#include "WingPackageMaker.h"
|
||||
#include "PackageTools.h"
|
||||
#include "Kismet2/KismetEditorUtilities.h"
|
||||
#include "Kismet2/EnumEditorUtils.h"
|
||||
#include "Factories/BlueprintFactory.h"
|
||||
@@ -62,6 +62,78 @@ void UWingFactories::DisableFactory(const TCHAR* Name)
|
||||
Entry->Disabled = true;
|
||||
}
|
||||
|
||||
|
||||
bool UWingFactories::CheckNewAssetPath(const FString& Path)
|
||||
{
|
||||
if (UPackageTools::SanitizePackageName(Path) != Path)
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Package path '%s' is not a valid package name\n"), *Path);
|
||||
return false;
|
||||
}
|
||||
if (!FPackageName::IsValidTextForLongPackageName(Path))
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Package path '%s' is not a valid package name\n"), *Path);
|
||||
return false;
|
||||
}
|
||||
if (!Path.StartsWith(TEXT("/Game")))
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Package path '%s' must start with '/Game'\n"), *Path);
|
||||
return false;
|
||||
}
|
||||
if (FindObject<UPackage>(nullptr, *Path))
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: An asset already exists at '%s'\n"), *Path);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
UPackage *UWingFactories::CreateNewPackage(const FString &Path)
|
||||
{
|
||||
UPackage *Pkg = CreatePackage(*Path);
|
||||
if (!Pkg)
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Failed to create package at '%s'\n"), *Path);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Pkg->ClearFlags(RF_Transient);
|
||||
Pkg->SetIsExternallyReferenceable(true);
|
||||
Pkg->MarkPackageDirty();
|
||||
return Pkg;
|
||||
}
|
||||
|
||||
|
||||
UObject* UWingFactories::CreateAsset(const FString& Path, UFactory* Factory)
|
||||
{
|
||||
// Validate the path, and that there's not already something there.
|
||||
if (!CheckNewAssetPath(Path)) return nullptr;
|
||||
FName Name = FName(FPackageName::GetShortName(Path));
|
||||
|
||||
// Pre-check: block factories that would cause problems.
|
||||
// In particular, this blocks those that would pop a dialog.
|
||||
if (!PreCheck(Factory, Name, Path)) return nullptr;
|
||||
|
||||
// Create the asset.
|
||||
UPackage *Package = CreateNewPackage(Path);
|
||||
UObject* NewAsset = Factory->FactoryCreateNew(
|
||||
Factory->GetSupportedClass(),
|
||||
Package,
|
||||
Name,
|
||||
RF_Public | RF_Standalone | RF_Transactional,
|
||||
nullptr,
|
||||
GWarn
|
||||
);
|
||||
if (!NewAsset)
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Factory '%s' returned null\n"), *Factory->GetClass()->GetName());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
UWingServer::Printf(TEXT("Created: %s\n"), *WingUtils::ExternalizeID(Name));
|
||||
return NewAsset;
|
||||
}
|
||||
|
||||
UObject* UWingFactories::CreateAsset(const FString& Path, const FString& FactoryName, FWingJsonObject& Config)
|
||||
{
|
||||
UWingFactories* Self = GEditor->GetEditorSubsystem<UWingFactories>();
|
||||
@@ -74,18 +146,13 @@ UObject* UWingFactories::CreateAsset(const FString& Path, const FString& Factory
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Make sure this is the a creation factory, as opposed to an import factory.
|
||||
// Make sure this is a creation factory, as opposed to an import factory.
|
||||
if (!FactoryInfo->CanCreateNew())
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Factory '%s' cannot create objects from scratch\n"), *FactoryName);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Validate the path, and that there's not already something there.
|
||||
WingPackageMaker Maker(Path);
|
||||
if (!Maker.Ok()) return nullptr;
|
||||
FName Name = Maker.GetFName();
|
||||
|
||||
// Create the factory instance.
|
||||
UFactory* Factory = NewObject<UFactory>(GetTransientPackage(), FactoryInfo->FactoryClass);
|
||||
|
||||
@@ -101,28 +168,7 @@ UObject* UWingFactories::CreateAsset(const FString& Path, const FString& Factory
|
||||
if (!FWingProperty::PopulateFromJson(Props, ConfigJson.Get(), false))
|
||||
return nullptr;
|
||||
|
||||
// Pre-check: block factories that would cause problems.
|
||||
// In particular, this blocks those that would pop a dialog.
|
||||
if (!PreCheck(Factory, Name, Path)) return nullptr;
|
||||
|
||||
// Create the asset.
|
||||
if (!Maker.Make()) return nullptr;
|
||||
UObject* NewAsset = Factory->FactoryCreateNew(
|
||||
FactoryInfo->FactoryClass->GetDefaultObject<UFactory>()->GetSupportedClass(),
|
||||
Maker.Package(),
|
||||
Name,
|
||||
RF_Public | RF_Standalone | RF_Transactional,
|
||||
nullptr,
|
||||
GWarn
|
||||
);
|
||||
if (!NewAsset)
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Factory '%s' returned null\n"), *FactoryName);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
UWingServer::Printf(TEXT("Created: %s\n"), *WingUtils::ExternalizeID(Name));
|
||||
return NewAsset;
|
||||
return CreateAsset(Path, Factory);
|
||||
}
|
||||
|
||||
bool UWingFactories::PreCheck(UFactory* Factory, FName Name, const FString &Path)
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
#include "WingHandler.h"
|
||||
#include "WingTypes.h"
|
||||
|
||||
void WingManual::PrintHandlerPrototype(UClass *HandlerClass)
|
||||
void WingManual::PrintHandlerPrototype(const FWingHandlerConfig& Handler)
|
||||
{
|
||||
UWingServer::Print(WingUtils::GetHandlerName(HandlerClass));
|
||||
UWingServer::Print(Handler.Name);
|
||||
UWingServer::Print(TEXT("("));
|
||||
bool bFirst = true;
|
||||
for (TFieldIterator<FProperty> PropIt(HandlerClass, EFieldIterationFlags::None); PropIt; ++PropIt)
|
||||
for (TFieldIterator<FProperty> PropIt(Handler.Class.Get(), EFieldIterationFlags::None); PropIt; ++PropIt)
|
||||
{
|
||||
if (!bFirst) UWingServer::Print(TEXT(","));
|
||||
bFirst = false;
|
||||
@@ -18,10 +18,10 @@ void WingManual::PrintHandlerPrototype(UClass *HandlerClass)
|
||||
UWingServer::Print(TEXT(")\n"));
|
||||
}
|
||||
|
||||
void WingManual::PrintHandlerArguments(UClass *HandlerClass)
|
||||
void WingManual::PrintHandlerArguments(const FWingHandlerConfig& Handler)
|
||||
{
|
||||
// parameter details
|
||||
for (TFieldIterator<FProperty> PropIt(HandlerClass, EFieldIterationFlags::None); PropIt; ++PropIt)
|
||||
for (TFieldIterator<FProperty> PropIt(Handler.Class.Get(), EFieldIterationFlags::None); PropIt; ++PropIt)
|
||||
{
|
||||
FProperty* Prop = *PropIt;
|
||||
FString Name = Prop->GetName();
|
||||
@@ -42,23 +42,23 @@ void WingManual::PrintHandlerArguments(UClass *HandlerClass)
|
||||
}
|
||||
}
|
||||
|
||||
void WingManual::PrintHandlerDescription(UClass *HandlerClass)
|
||||
void WingManual::PrintHandlerDescription(const FWingHandlerConfig& Handler)
|
||||
{
|
||||
const IWingHandler* Handler = Cast<IWingHandler>(HandlerClass->GetDefaultObject());
|
||||
if (!Handler) return;
|
||||
UWingServer::Print(WingUtils::WrapText(Handler->GetDescription(), 80, TEXT(" // ")));
|
||||
const UWingHandler* HandlerCDO = Cast<UWingHandler>(Handler.Class->GetDefaultObject());
|
||||
if (!HandlerCDO) return;
|
||||
UWingServer::Print(WingUtils::WrapText(HandlerCDO->GetDescription(), 80, TEXT(" // ")));
|
||||
}
|
||||
|
||||
void WingManual::PrintHandlerHelp(UClass* HandlerClass)
|
||||
void WingManual::PrintHandlerHelp(const FWingHandlerConfig& Handler)
|
||||
{
|
||||
UWingServer::Print(TEXT("\n"));
|
||||
PrintHandlerPrototype(HandlerClass);
|
||||
PrintHandlerArguments(HandlerClass);
|
||||
PrintHandlerDescription(HandlerClass);
|
||||
PrintHandlerPrototype(Handler);
|
||||
PrintHandlerArguments(Handler);
|
||||
PrintHandlerDescription(Handler);
|
||||
UWingServer::Print(TEXT("\n"));
|
||||
}
|
||||
|
||||
void WingManual::PrintManual(TSet<Section> Sections, UClass *Handler, bool Abridged)
|
||||
void WingManual::PrintManual(TSet<Section> Sections, const FWingHandlerConfig* Handler, bool Abridged)
|
||||
{
|
||||
if (Sections.IsEmpty()) return;
|
||||
|
||||
@@ -71,7 +71,7 @@ void WingManual::PrintManual(TSet<Section> Sections, UClass *Handler, bool Abrid
|
||||
|
||||
if (Handler && (Sections.Contains(Section::HandlerHelp) || bPrintAll))
|
||||
{
|
||||
PrintHandlerHelp(Handler);
|
||||
PrintHandlerHelp(*Handler);
|
||||
}
|
||||
|
||||
if (Sections.Contains(Section::Paths) || bPrintAll)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "WingPackageMaker.h"
|
||||
#include "PackageTools.h"
|
||||
#include "AssetRegistry/AssetRegistryModule.h"
|
||||
|
||||
WingPackageMaker::WingPackageMaker(const FString& InFullPath)
|
||||
@@ -13,6 +14,11 @@ WingPackageMaker::WingPackageMaker(const FString& InFullPath)
|
||||
|
||||
bool WingPackageMaker::CheckNewAssetPath(const FString& Path)
|
||||
{
|
||||
if (UPackageTools::SanitizePackageName(Path) != Path)
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Package path '%s' is not a valid package name\n"), *Path);
|
||||
return false;
|
||||
}
|
||||
if (!FPackageName::IsValidTextForLongPackageName(Path))
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Package path '%s' is not a valid package name\n"), *Path);
|
||||
|
||||
@@ -265,7 +265,7 @@ FString UWingServer::HandleRequest(const FString& Line)
|
||||
LogCapture.bEnabled = true;
|
||||
HandlerOutput.Reset();
|
||||
SuggestedManualSections.Empty();
|
||||
LastHandlerClass = nullptr;
|
||||
LastHandler = nullptr;
|
||||
|
||||
TryCallHandler(Line);
|
||||
|
||||
@@ -279,7 +279,7 @@ FString UWingServer::HandleRequest(const FString& Line)
|
||||
if (!SuggestedManualSections.IsEmpty())
|
||||
{
|
||||
UWingServer::SuggestManual(WingManual::Section::HandlerHelp);
|
||||
WingManual::PrintManual(SuggestedManualSections, LastHandlerClass, true);
|
||||
WingManual::PrintManual(SuggestedManualSections, LastHandler, true);
|
||||
}
|
||||
FString Result = HandlerOutput.ToString();
|
||||
HandlerOutput.Reset();
|
||||
@@ -312,19 +312,20 @@ void UWingServer::TryCallHandler(const FString &Line)
|
||||
}
|
||||
Request->RemoveField(TEXT("command"));
|
||||
|
||||
// Find the handler UClass for the specified command.
|
||||
TObjectPtr<UClass>* HandlerClass = WingHandlerRegistry.Find(Command);
|
||||
if (!HandlerClass)
|
||||
// Find the handler for the specified command.
|
||||
FWingHandlerConfig* Found = FindHandler(Command);
|
||||
if (!Found)
|
||||
{
|
||||
UWingServer::Printf(TEXT("Unknown command: %s"), *Command);
|
||||
UWingServer::SuggestManual(WingManual::Section::ImportantCommands);
|
||||
return;
|
||||
}
|
||||
LastHandlerClass = *HandlerClass;
|
||||
LastHandler = Found;
|
||||
|
||||
// Make an object of the handler class.
|
||||
TStrongObjectPtr<UObject> HandlerObj(NewObject<UObject>(GetTransientPackage(), *HandlerClass));
|
||||
IWingHandler* Handler = Cast<IWingHandler>(HandlerObj.Get());
|
||||
TStrongObjectPtr<UObject> HandlerObj(NewObject<UObject>(GetTransientPackage(), Found->Class.Get()));
|
||||
UWingHandler* Handler = Cast<UWingHandler>(HandlerObj.Get());
|
||||
Handler->ConfigurationObject = Found->Config.Get();
|
||||
|
||||
// Populate the handler object with the request parameters.
|
||||
if (!FWingProperty::PopulateFromJson(HandlerObj->GetClass(), HandlerObj.Get(), &*Request))
|
||||
@@ -451,10 +452,39 @@ void UWingServer::ClientThreadFunc(UWingServer* Server, TSharedPtr<FClientConnec
|
||||
// BuildWingHandlerRegistry
|
||||
// ============================================================
|
||||
|
||||
void UWingHandler::Register(UWingServer* Server)
|
||||
{
|
||||
UClass* Class = GetClass();
|
||||
Server->AddHandler(WingUtils::GetHandlerName(Class), Class, nullptr, EWingHandlerKind::Normal);
|
||||
}
|
||||
|
||||
void UWingServer::AddHandler(const FString& Name, UClass* Class, UObject* Config, EWingHandlerKind Kind)
|
||||
{
|
||||
FWingHandlerConfig H;
|
||||
H.Name = Name;
|
||||
H.Class = TStrongObjectPtr<UClass>(Class);
|
||||
H.Config = TStrongObjectPtr<UObject>(Config);
|
||||
H.Kind = Kind;
|
||||
|
||||
WingHandlerRegistry.Add(MoveTemp(H));
|
||||
}
|
||||
|
||||
void UWingServer::BuildWingHandlerRegistry()
|
||||
{
|
||||
for (UClass* Class : WingUtils::CollectHandlerClasses())
|
||||
{
|
||||
WingHandlerRegistry.FindOrAdd(WingUtils::GetHandlerName(Class)) = Class;
|
||||
UWingHandler* CDO = Cast<UWingHandler>(Class->GetDefaultObject());
|
||||
CDO->Register(this);
|
||||
}
|
||||
WingHandlerRegistry.Sort([](const FWingHandlerConfig& A, const FWingHandlerConfig& B) { return A.Name < B.Name; });
|
||||
}
|
||||
|
||||
FWingHandlerConfig* UWingServer::FindHandler(const FString& Name)
|
||||
{
|
||||
int32 Index = Algo::LowerBoundBy(WingHandlerRegistry, Name, [](const FWingHandlerConfig& H) { return H.Name; });
|
||||
if (Index < WingHandlerRegistry.Num() && WingHandlerRegistry[Index].Name == Name)
|
||||
{
|
||||
return &WingHandlerRegistry[Index];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -600,7 +600,7 @@ TArray<UClass*> WingUtils::CollectHandlerClasses()
|
||||
{
|
||||
UClass* Class = *It;
|
||||
if (Class->HasAnyClassFlags(CLASS_Abstract)) continue;
|
||||
if (!Class->ImplementsInterface(UWingHandler::StaticClass())) continue;
|
||||
if (!Class->IsChildOf(UWingHandler::StaticClass())) continue;
|
||||
Result.Add(Class);
|
||||
}
|
||||
Result.Sort([](UClass& A, UClass& B) { return GetHandlerName(&A) < GetHandlerName(&B); });
|
||||
|
||||
@@ -26,17 +26,22 @@ public:
|
||||
|
||||
static const TArray<Info>& AllFactories();
|
||||
|
||||
// Create an asset on disk, using a factory. Returns the main object.
|
||||
// Create an asset on disk, using a factory instance. Returns the main object.
|
||||
// If there are problems, prints error messages and returns nullptr.
|
||||
static UObject *CreateAsset(const FString &Path, const FString &Factory, FWingJsonObject &Config);
|
||||
static UObject *CreateAsset(const FString &Path, UFactory *Factory);
|
||||
|
||||
// Create an asset on disk, looking up the factory by name and configuring it.
|
||||
static UObject *CreateAsset(const FString &Path, const FString &FactoryName, FWingJsonObject &Config);
|
||||
|
||||
static FString DeriveFactoryName(UClass* FactoryClass);
|
||||
|
||||
private:
|
||||
TArray<Info> Registry;
|
||||
|
||||
Info* Find(const FString& Name);
|
||||
|
||||
static UPackage *CreateNewPackage(const FString &Path);
|
||||
static bool CheckNewAssetPath(const FString &Path);
|
||||
void PopulateRegistry();
|
||||
void DisableFactory(const TCHAR* Name);
|
||||
static bool PreCheck(UFactory *Factory, FName Name, const FString &Path);
|
||||
static FString DeriveFactoryName(UClass* FactoryClass);
|
||||
};
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/Interface.h"
|
||||
#include "UObject/Object.h"
|
||||
#include "UObject/StrongObjectPtr.h"
|
||||
#include "Dom/JsonObject.h"
|
||||
#include "WingHandler.generated.h"
|
||||
|
||||
@@ -24,32 +24,40 @@ struct FWingJsonArray
|
||||
TArray<TSharedPtr<FJsonValue>> Array;
|
||||
};
|
||||
|
||||
// Interface for self-registering MCP tool handlers.
|
||||
//
|
||||
// Implementing classes declare their parameters as UPROPERTY fields, which are
|
||||
// automatically populated from the incoming JSON request and used to
|
||||
// generate the tool's JSON Schema for MCP tools/list.
|
||||
//
|
||||
// Class metadata:
|
||||
// ToolName - the MCP tool name (e.g. "spawn_node")
|
||||
//
|
||||
// Property metadata:
|
||||
// Optional - marks a parameter as not required
|
||||
//
|
||||
UINTERFACE(MinimalAPI, meta=(CannotImplementInterfaceInBlueprint))
|
||||
class UWingHandler : public UInterface
|
||||
class UWingServer;
|
||||
|
||||
UENUM()
|
||||
enum class EWingHandlerKind
|
||||
{
|
||||
GENERATED_BODY()
|
||||
Normal,
|
||||
Create
|
||||
};
|
||||
|
||||
class UEWINGMAN_API IWingHandler
|
||||
USTRUCT()
|
||||
struct FWingHandlerConfig
|
||||
{
|
||||
GENERATED_BODY()
|
||||
FString Name;
|
||||
TStrongObjectPtr<UClass> Class;
|
||||
TStrongObjectPtr<UObject> Config;
|
||||
EWingHandlerKind Kind = EWingHandlerKind::Normal;
|
||||
};
|
||||
|
||||
UCLASS(Abstract)
|
||||
class UEWINGMAN_API UWingHandler : public UObject
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
// Human-readable tool description for MCP tools/list.
|
||||
virtual FString GetDescription() const = 0;
|
||||
virtual FString GetDescription() const PURE_VIRTUAL(UWingHandler::GetDescription, return FString(););
|
||||
|
||||
// Register this handler's commands with the server.
|
||||
virtual void Register(UWingServer* Server);
|
||||
|
||||
// Called after parameter fields have been populated from JSON.
|
||||
virtual void Handle() {}
|
||||
|
||||
// The configuration object.
|
||||
UObject *ConfigurationObject;
|
||||
};
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
#include "Containers/Set.h"
|
||||
#include "WingHandler.h"
|
||||
|
||||
class WingManual
|
||||
{
|
||||
@@ -17,9 +18,9 @@ public:
|
||||
ImportantCommands,
|
||||
};
|
||||
|
||||
static void PrintHandlerPrototype(UClass *Handler);
|
||||
static void PrintHandlerArguments(UClass *Handler);
|
||||
static void PrintHandlerDescription(UClass *Handler);
|
||||
static void PrintHandlerHelp(UClass *Handler);
|
||||
static void PrintManual(TSet<Section> Sections, UClass *Handler, bool Abridged);
|
||||
static void PrintHandlerPrototype(const FWingHandlerConfig& Handler);
|
||||
static void PrintHandlerArguments(const FWingHandlerConfig& Handler);
|
||||
static void PrintHandlerDescription(const FWingHandlerConfig& Handler);
|
||||
static void PrintHandlerHelp(const FWingHandlerConfig& Handler);
|
||||
static void PrintManual(TSet<Section> Sections, const FWingHandlerConfig* Handler, bool Abridged);
|
||||
};
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "WingUtils.h"
|
||||
#include "WingNotifier.h"
|
||||
#include "WingLogCapture.h"
|
||||
#include "WingHandler.h"
|
||||
#include "WingManual.h"
|
||||
#include "WingServer.generated.h"
|
||||
|
||||
@@ -72,19 +73,22 @@ public:
|
||||
/** Port the server is listening on. */
|
||||
int32 GetPort() const { return Port; }
|
||||
|
||||
// ----- Tool dispatch -----
|
||||
void AddHandler(const FString& Name, UClass* Class, UObject* Config, EWingHandlerKind Kind);
|
||||
static const TArray<FWingHandlerConfig>& AllHandlers() { return GWingServer->WingHandlerRegistry; }
|
||||
|
||||
private:
|
||||
static UWingServer* GWingServer;
|
||||
|
||||
// ----- Tool dispatch -----
|
||||
UPROPERTY()
|
||||
FWingNotifier Notifier;
|
||||
UClass* LastHandlerClass;
|
||||
FWingHandlerConfig* LastHandler;
|
||||
TStringBuilder<16384> HandlerOutput;
|
||||
TSet<WingManual::Section> SuggestedManualSections;
|
||||
FLogCaptureOutputDevice LogCapture; // installed once at startup, enabled per-request
|
||||
UPROPERTY()
|
||||
TMap<FString, TObjectPtr<UClass>> WingHandlerRegistry; // tool name -> UWingHandler subclass
|
||||
TArray<FWingHandlerConfig> WingHandlerRegistry; // sorted by Name
|
||||
void BuildWingHandlerRegistry();
|
||||
FWingHandlerConfig* FindHandler(const FString& Name);
|
||||
|
||||
// Handle a complete JSON line and return the response JSON
|
||||
FString HandleRequest(const FString& Line);
|
||||
|
||||
Reference in New Issue
Block a user