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;
|
FString Blueprint;
|
||||||
|
|
||||||
UPROPERTY(meta=(Description="Name of the new event dispatcher"))
|
UPROPERTY(meta=(Description="Name of the new event dispatcher"))
|
||||||
FString Name;
|
FString Dispatcher;
|
||||||
|
|
||||||
UPROPERTY(meta=(Description="Arguments expressed as: int x,float y"))
|
UPROPERTY(meta=(Description="Arguments expressed as: int x,float y"))
|
||||||
FString Arguments;
|
FString Arguments;
|
||||||
@@ -44,9 +44,9 @@ public:
|
|||||||
if (!BP) return;
|
if (!BP) return;
|
||||||
|
|
||||||
// Check for valid proposed name
|
// Check for valid proposed name
|
||||||
if (!WingUtils::FindExactlyNoneNamed(Name, BP->NewVariables, TEXT("Variable"))) return;
|
if (!WingUtils::FindExactlyNoneNamed(Dispatcher, BP->NewVariables, TEXT("Variable"))) return;
|
||||||
if (!WingUtils::FindExactlyNoneNamed(Name, WingUtils::AllGraphs(BP), TEXT("Graph"))) return;
|
if (!WingUtils::FindExactlyNoneNamed(Dispatcher, WingUtils::AllGraphs(BP), TEXT("Graph"))) return;
|
||||||
FString InternalName = WingUtils::CheckProposedName(Name);
|
FString InternalName = WingUtils::CheckProposedName(Dispatcher);
|
||||||
if (InternalName.IsEmpty()) return;
|
if (InternalName.IsEmpty()) return;
|
||||||
FName VarFName(InternalName);
|
FName VarFName(InternalName);
|
||||||
|
|
||||||
@@ -58,7 +58,7 @@ public:
|
|||||||
DelegateType.PinCategory = UEdGraphSchema_K2::PC_MCDelegate;
|
DelegateType.PinCategory = UEdGraphSchema_K2::PC_MCDelegate;
|
||||||
if (!FBlueprintEditorUtils::AddMemberVariable(BP, VarFName, DelegateType))
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,7 +68,7 @@ public:
|
|||||||
UEdGraph::StaticClass(), UEdGraphSchema_K2::StaticClass());
|
UEdGraph::StaticClass(), UEdGraphSchema_K2::StaticClass());
|
||||||
if (!SigGraph)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,6 +90,6 @@ public:
|
|||||||
}
|
}
|
||||||
if (!WingFunctionArgs::SetArgs(EntryNode.Get(), Arguments)) return;
|
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