Event dispatcher support complete
This commit is contained in:
@@ -1,142 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "WingServer.h"
|
||||
#include "WingHandler.h"
|
||||
#include "WingTypes.h"
|
||||
#include "WingFetcher.h"
|
||||
#include "WingJson.h"
|
||||
#include "WingUtils.h"
|
||||
#include "Engine/Blueprint.h"
|
||||
#include "EdGraph/EdGraph.h"
|
||||
#include "EdGraph/EdGraphPin.h"
|
||||
#include "K2Node_FunctionEntry.h"
|
||||
#include "K2Node_EditablePinBase.h"
|
||||
#include "Kismet2/BlueprintEditorUtils.h"
|
||||
#include "Blueprint_AddEventDispatcher.generated.h"
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// ---------------------------------------------------------------------------
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
USTRUCT()
|
||||
struct FDispatcherParamEntry
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY()
|
||||
FString Name;
|
||||
|
||||
UPROPERTY()
|
||||
FString Type;
|
||||
};
|
||||
|
||||
UCLASS()
|
||||
class UWing_Blueprint_AddEventDispatcher : public UObject, public IWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY(meta=(Description="Path to a blueprint, e.g. /Game/Foo/MyBlueprint"))
|
||||
FString Blueprint;
|
||||
|
||||
UPROPERTY(meta=(Description="Name for the new event dispatcher"))
|
||||
FString DispatcherName;
|
||||
|
||||
UPROPERTY(meta=(Optional, Description="Array of parameter objects, each with 'name' and 'type' fields"))
|
||||
FWingJsonArray Parameters;
|
||||
|
||||
virtual FString GetDescription() const override
|
||||
{
|
||||
return TEXT("Create a new multicast event dispatcher on a Blueprint, optionally with parameters.");
|
||||
}
|
||||
|
||||
virtual void Handle() override
|
||||
{
|
||||
WingFetcher F;
|
||||
UBlueprint* BP = F.Walk(Blueprint).Cast<UBlueprint>();
|
||||
if (!BP) return;
|
||||
|
||||
FName DispatcherFName(*DispatcherName);
|
||||
|
||||
// Check for name uniqueness against existing variables
|
||||
for (const FBPVariableDescription& Var : BP->NewVariables)
|
||||
{
|
||||
if (Var.VarName == DispatcherFName)
|
||||
{
|
||||
UWingServer::Printf(TEXT("Error: A variable or dispatcher named '%s' already exists.\n"), *DispatcherName);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Check against existing graphs (functions, macros, etc.)
|
||||
if (!WingUtils::FindExactlyNoneNamed(DispatcherName, WingUtils::AllGraphs(BP), TEXT("Graph")))
|
||||
return;
|
||||
|
||||
// Add a member variable with PC_MCDelegate pin type
|
||||
FEdGraphPinType DelegateType;
|
||||
DelegateType.PinCategory = UEdGraphSchema_K2::PC_MCDelegate;
|
||||
if (!FBlueprintEditorUtils::AddMemberVariable(BP, DispatcherFName, DelegateType))
|
||||
{
|
||||
UWingServer::Printf(TEXT("Error: Failed to add delegate variable for '%s'.\n"), *DispatcherName);
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the signature graph
|
||||
const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>();
|
||||
|
||||
UEdGraph* SigGraph = FBlueprintEditorUtils::CreateNewGraph(BP, DispatcherFName,
|
||||
UEdGraph::StaticClass(), UEdGraphSchema_K2::StaticClass());
|
||||
if (!SigGraph)
|
||||
{
|
||||
UWingServer::Print(TEXT("Error: Failed to create delegate signature graph.\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
K2Schema->CreateDefaultNodesForGraph(*SigGraph);
|
||||
K2Schema->CreateFunctionGraphTerminators(*SigGraph, static_cast<UClass*>(nullptr));
|
||||
K2Schema->AddExtraFunctionFlags(SigGraph, FUNC_BlueprintCallable | FUNC_BlueprintEvent | FUNC_Public);
|
||||
K2Schema->MarkFunctionEntryAsEditable(SigGraph, true);
|
||||
|
||||
BP->DelegateSignatureGraphs.Add(SigGraph);
|
||||
|
||||
// Add parameters if provided
|
||||
int32 ParamCount = 0;
|
||||
|
||||
if (Parameters.Array.Num() > 0)
|
||||
{
|
||||
UK2Node_EditablePinBase* EntryNode = nullptr;
|
||||
for (UK2Node_FunctionEntry* FE : WingUtils::AllNodes<UK2Node_FunctionEntry>(SigGraph))
|
||||
{
|
||||
EntryNode = FE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!EntryNode)
|
||||
{
|
||||
UWingServer::Print(TEXT("Error: Event dispatcher created but entry node not found — parameters could not be added.\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
for (const TSharedPtr<FJsonValue>& ParamVal : Parameters.Array)
|
||||
{
|
||||
FDispatcherParamEntry Entry;
|
||||
if (!WingJson::PopulateFromJson(FDispatcherParamEntry::StaticStruct(), &Entry, ParamVal)) return;
|
||||
if (Entry.Name.IsEmpty() || Entry.Type.IsEmpty()) continue;
|
||||
|
||||
FEdGraphPinType PinType;
|
||||
if (!UWingTypes::TextToType(Entry.Type, PinType))
|
||||
return;
|
||||
|
||||
EntryNode->CreateUserDefinedPin(FName(*Entry.Name), PinType, EGPD_Output);
|
||||
ParamCount++;
|
||||
}
|
||||
}
|
||||
|
||||
UWingServer::Printf(TEXT("Created event dispatcher '%s'"), *DispatcherName);
|
||||
if (ParamCount > 0)
|
||||
UWingServer::Printf(TEXT(" with %d parameter(s)"), ParamCount);
|
||||
UWingServer::Print(TEXT(".\n"));
|
||||
}
|
||||
};
|
||||
@@ -27,7 +27,7 @@ public:
|
||||
FString Blueprint;
|
||||
|
||||
UPROPERTY(meta=(Description="Name of the new event dispatcher"))
|
||||
FString Name;
|
||||
FString Dispatcher;
|
||||
|
||||
UPROPERTY(meta=(Description="Arguments expressed as: int x,float y"))
|
||||
FString Arguments;
|
||||
@@ -44,9 +44,9 @@ public:
|
||||
if (!BP) return;
|
||||
|
||||
// Check for valid proposed name
|
||||
if (!WingUtils::FindExactlyNoneNamed(Name, BP->NewVariables, TEXT("Variable"))) return;
|
||||
if (!WingUtils::FindExactlyNoneNamed(Name, WingUtils::AllGraphs(BP), TEXT("Graph"))) return;
|
||||
FString InternalName = WingUtils::CheckProposedName(Name);
|
||||
if (!WingUtils::FindExactlyNoneNamed(Dispatcher, BP->NewVariables, TEXT("Variable"))) return;
|
||||
if (!WingUtils::FindExactlyNoneNamed(Dispatcher, WingUtils::AllGraphs(BP), TEXT("Graph"))) return;
|
||||
FString InternalName = WingUtils::CheckProposedName(Dispatcher);
|
||||
if (InternalName.IsEmpty()) return;
|
||||
FName VarFName(InternalName);
|
||||
|
||||
@@ -58,7 +58,7 @@ public:
|
||||
DelegateType.PinCategory = UEdGraphSchema_K2::PC_MCDelegate;
|
||||
if (!FBlueprintEditorUtils::AddMemberVariable(BP, VarFName, DelegateType))
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Failed to add event dispatcher '%s' to %s\n"), *Name, *WingUtils::FormatName(BP));
|
||||
UWingServer::Printf(TEXT("ERROR: Failed to add event dispatcher '%s' to %s\n"), *Dispatcher, *WingUtils::FormatName(BP));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ public:
|
||||
UEdGraph::StaticClass(), UEdGraphSchema_K2::StaticClass());
|
||||
if (!SigGraph)
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Failed to create signature graph for '%s'\n"), *Name);
|
||||
UWingServer::Printf(TEXT("ERROR: Failed to create signature graph for '%s'\n"), *Dispatcher);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -90,6 +90,6 @@ public:
|
||||
}
|
||||
if (!WingFunctionArgs::SetArgs(EntryNode.Get(), Arguments)) return;
|
||||
|
||||
UWingServer::Printf(TEXT("Created event dispatcher %s in %s\n"), *Name, *WingUtils::FormatName(BP));
|
||||
UWingServer::Printf(TEXT("Created event dispatcher %s in %s\n"), *Dispatcher, *WingUtils::FormatName(BP));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "WingServer.h"
|
||||
#include "WingHandler.h"
|
||||
#include "WingFetcher.h"
|
||||
#include "WingUtils.h"
|
||||
#include "Engine/Blueprint.h"
|
||||
#include "Kismet2/BlueprintEditorUtils.h"
|
||||
#include "BlueprintDispatcher_Delete.generated.h"
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// ---------------------------------------------------------------------------
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_BlueprintDispatcher_Delete : public UObject, public IWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY(meta=(Description="Blueprint name or package path"))
|
||||
FString Blueprint;
|
||||
|
||||
UPROPERTY(meta=(Description="Name of the event dispatcher to delete"))
|
||||
FString Dispatcher;
|
||||
|
||||
virtual FString GetDescription() const override
|
||||
{
|
||||
return TEXT("Delete an event dispatcher from a Blueprint.");
|
||||
}
|
||||
|
||||
virtual void Handle() override
|
||||
{
|
||||
WingFetcher F;
|
||||
UBlueprint* BP = F.Walk(Blueprint).Cast<UBlueprint>();
|
||||
if (!BP) return;
|
||||
|
||||
FBPVariableDescription* Var = WingUtils::FindExactlyOneNamed(Dispatcher, BP->NewVariables, TEXT("Dispatcher"));
|
||||
if (!Var) return;
|
||||
TObjectPtr<UEdGraph>* SigGraph = WingUtils::FindExactlyOneNamed(Dispatcher, BP->DelegateSignatureGraphs, TEXT("Dispatcher Signature Graph"));
|
||||
if (!SigGraph) return;
|
||||
|
||||
UEdGraph* Graph = *SigGraph;
|
||||
FName VarFName = Var->VarName;
|
||||
|
||||
BP->Modify();
|
||||
Graph->Modify();
|
||||
|
||||
// Remove the member variable (also destroys referencing nodes)
|
||||
FBlueprintEditorUtils::RemoveMemberVariable(BP, VarFName);
|
||||
|
||||
// Remove the signature graph
|
||||
FBlueprintEditorUtils::RemoveGraph(BP, Graph, EGraphRemoveFlags::Recompile);
|
||||
|
||||
UWingServer::Printf(TEXT("Deleted event dispatcher %s from %s\n"), *Dispatcher, *WingUtils::FormatName(BP));
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,64 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "WingServer.h"
|
||||
#include "WingHandler.h"
|
||||
#include "WingFetcher.h"
|
||||
#include "WingUtils.h"
|
||||
#include "WingFunctionArgs.h"
|
||||
#include "Engine/Blueprint.h"
|
||||
#include "Kismet2/BlueprintEditorUtils.h"
|
||||
#include "BlueprintDispatcher_Modify.generated.h"
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// ---------------------------------------------------------------------------
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_BlueprintDispatcher_Modify : public UObject, public IWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY(meta=(Description="Blueprint name or package path"))
|
||||
FString Blueprint;
|
||||
|
||||
UPROPERTY(meta=(Description="Name of the event dispatcher to modify"))
|
||||
FString Dispatcher;
|
||||
|
||||
UPROPERTY(meta=(Description="New arguments expressed as: int x,float y"))
|
||||
FString Arguments;
|
||||
|
||||
virtual FString GetDescription() const override
|
||||
{
|
||||
return TEXT("Modify the arguments of an existing Blueprint event dispatcher.");
|
||||
}
|
||||
|
||||
virtual void Handle() override
|
||||
{
|
||||
WingFetcher F;
|
||||
UBlueprint* BP = F.Walk(Blueprint).Cast<UBlueprint>();
|
||||
if (!BP) return;
|
||||
|
||||
FBPVariableDescription* Var = WingUtils::FindExactlyOneNamed(Dispatcher, BP->NewVariables, TEXT("Dispatcher"));
|
||||
if (!Var) return;
|
||||
TObjectPtr<UEdGraph>* SigGraph = WingUtils::FindExactlyOneNamed(Dispatcher, BP->DelegateSignatureGraphs, TEXT("Dispatcher Signature Graph"));
|
||||
if (!SigGraph) return;
|
||||
|
||||
// Make sure the argument types are valid.
|
||||
if (!WingFunctionArgs::CheckArgs(Arguments)) return;
|
||||
|
||||
TWeakObjectPtr<UK2Node_EditablePinBase> EntryNode;
|
||||
TWeakObjectPtr<UK2Node_EditablePinBase> ResultNode;
|
||||
FBlueprintEditorUtils::GetEntryAndResultNodes(*SigGraph, EntryNode, ResultNode);
|
||||
if (!EntryNode.IsValid())
|
||||
{
|
||||
UWingServer::Print(TEXT("ERROR: Entry node not found in delegate signature graph\n"));
|
||||
return;
|
||||
}
|
||||
if (!WingFunctionArgs::SetArgs(EntryNode.Get(), Arguments)) return;
|
||||
|
||||
UWingServer::Printf(TEXT("Modified event dispatcher %s in %s\n"), *Dispatcher, *WingUtils::FormatName(BP));
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user