Halfway done with Dispatcher stuff
This commit is contained in:
BIN
Content/Testing/BP_Test.uasset
LFS
BIN
Content/Testing/BP_Test.uasset
LFS
Binary file not shown.
@@ -0,0 +1,100 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "WingServer.h"
|
||||
#include "WingHandler.h"
|
||||
#include "WingFetcher.h"
|
||||
#include "WingJson.h"
|
||||
#include "WingBlueprintVar.h"
|
||||
#include "WingUtils.h"
|
||||
#include "Engine/Blueprint.h"
|
||||
#include "EdGraphSchema_K2.h"
|
||||
#include "Kismet2/BlueprintEditorUtils.h"
|
||||
#include "BlueprintDispatcher_Create.generated.h"
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// ---------------------------------------------------------------------------
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_BlueprintDispatcher_Create : public UObject, public IWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY(meta=(Description="Blueprint name or package path"))
|
||||
FString Blueprint;
|
||||
|
||||
UPROPERTY(meta=(Description="Name of the new event dispatcher"))
|
||||
FString Name;
|
||||
|
||||
UPROPERTY(meta=(Optional, Description="Configuration: DelegateArgs, Category, Description, InstanceEditable, BlueprintReadOnly, Private, etc."))
|
||||
FWingJsonObject Config;
|
||||
|
||||
virtual FString GetDescription() const override
|
||||
{
|
||||
return TEXT("Add a new event dispatcher to a Blueprint. Pass Config to set parameters, category, flags, etc.");
|
||||
}
|
||||
|
||||
virtual void Handle() override
|
||||
{
|
||||
WingFetcher F;
|
||||
UBlueprint* BP = F.Walk(Blueprint).Cast<UBlueprint>();
|
||||
if (!BP) return;
|
||||
|
||||
// Check for duplicate variable name
|
||||
FName VarFName(*WingUtils::UnsanitizeName(Name));
|
||||
if (FBlueprintEditorUtils::FindNewVariableIndex(BP, VarFName) != INDEX_NONE)
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Variable or dispatcher '%s' already exists in %s\n"), *Name, *WingUtils::FormatName(BP));
|
||||
return;
|
||||
}
|
||||
for (UEdGraph* Graph : WingUtils::AllGraphs(BP))
|
||||
{
|
||||
if (Graph->GetFName() == VarFName)
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: A graph named '%s' already exists in %s\n"), *Name, *WingUtils::FormatName(BP));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Add the delegate variable
|
||||
FEdGraphPinType DelegateType;
|
||||
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));
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the signature graph
|
||||
const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>();
|
||||
UEdGraph* SigGraph = FBlueprintEditorUtils::CreateNewGraph(BP, VarFName,
|
||||
UEdGraph::StaticClass(), UEdGraphSchema_K2::StaticClass());
|
||||
if (!SigGraph)
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Failed to create signature graph for '%s'\n"), *Name);
|
||||
return;
|
||||
}
|
||||
|
||||
SigGraph->bEditable = false;
|
||||
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);
|
||||
|
||||
// Find the newly created variable and apply config
|
||||
FWingBlueprintVar Editor(BP, Name);
|
||||
if (Editor.NotFound()) return;
|
||||
|
||||
if (Config.Json && Config.Json->Values.Num() > 0)
|
||||
{
|
||||
if (!Editor.ApplyJson(Config.Json.Get()))
|
||||
return;
|
||||
}
|
||||
|
||||
UWingServer::Printf(TEXT("Created event dispatcher %s in %s\n"), *Name, *WingUtils::FormatName(BP));
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,51 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "WingServer.h"
|
||||
#include "WingHandler.h"
|
||||
#include "WingFetcher.h"
|
||||
#include "WingUtils.h"
|
||||
#include "WingBlueprintVar.h"
|
||||
#include "Engine/Blueprint.h"
|
||||
#include "BlueprintDispatcher_Dump.generated.h"
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// ---------------------------------------------------------------------------
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_BlueprintDispatcher_Dump : 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 inspect"))
|
||||
FString Dispatcher;
|
||||
|
||||
virtual FString GetDescription() const override
|
||||
{
|
||||
return TEXT("Show all editable properties of a Blueprint event dispatcher.");
|
||||
}
|
||||
|
||||
virtual void Handle() override
|
||||
{
|
||||
WingFetcher F;
|
||||
UBlueprint* BP = F.Walk(Blueprint).Cast<UBlueprint>();
|
||||
if (!BP) return;
|
||||
|
||||
FWingBlueprintVar Editor(BP, Dispatcher);
|
||||
if (Editor.NotFound()) return;
|
||||
if (!Editor.IsEventDispatcher())
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: '%s' is not an event dispatcher\n"), *Dispatcher);
|
||||
return;
|
||||
}
|
||||
|
||||
UWingServer::Printf(TEXT("Event dispatcher %s in %s:\n"), *Dispatcher, *WingUtils::FormatName(BP));
|
||||
Editor.Dump();
|
||||
}
|
||||
};
|
||||
@@ -67,6 +67,7 @@ public:
|
||||
UWingServer::Print(TEXT("\nVariables:\n"));
|
||||
for (const FBPVariableDescription& V : BP->NewVariables)
|
||||
{
|
||||
if (V.VarType.PinCategory == UEdGraphSchema_K2::PC_MCDelegate) continue;
|
||||
UWingServer::Printf(TEXT(" %s %s"),
|
||||
*UWingTypes::TypeToText(V.VarType),
|
||||
*WingUtils::FormatName(V));
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
#include "WingBlueprintVar.h"
|
||||
#include "WingFunctionArgs.h"
|
||||
#include "WingJson.h"
|
||||
#include "WingServer.h"
|
||||
#include "WingTypes.h"
|
||||
#include "WingUtils.h"
|
||||
#include "EdGraphSchema_K2.h"
|
||||
#include "K2Node_EditablePinBase.h"
|
||||
#include "Kismet2/BlueprintEditorUtils.h"
|
||||
|
||||
FWingBlueprintVar::FWingBlueprintVar(UBlueprint* BP, const FString& VarName)
|
||||
@@ -11,13 +13,34 @@ FWingBlueprintVar::FWingBlueprintVar(UBlueprint* BP, const FString& VarName)
|
||||
Desc = WingUtils::FindExactlyOneNamed(VarName, BP->NewVariables);
|
||||
if (!Desc) return;
|
||||
|
||||
// Try to find the default value property on the CDO.
|
||||
if (BP->GeneratedClass)
|
||||
if (Desc->VarType.PinCategory == UEdGraphSchema_K2::PC_MCDelegate)
|
||||
{
|
||||
UObject* CDO = BP->GeneratedClass->GetDefaultObject();
|
||||
FProperty* Prop = BP->GeneratedClass->FindPropertyByName(Desc->VarName);
|
||||
if (CDO && Prop)
|
||||
DefaultValueProp = FWingProperty(Prop, CDO);
|
||||
// Find the matching signature graph by name.
|
||||
for (UEdGraph* Graph : BP->DelegateSignatureGraphs)
|
||||
{
|
||||
if (Graph->GetFName() == Desc->VarName)
|
||||
{
|
||||
SigGraph = Graph;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!SigGraph)
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Signature graph not found for event dispatcher '%s'\n"), *VarName);
|
||||
Desc = nullptr;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Try to find the default value property on the CDO.
|
||||
if (BP->GeneratedClass)
|
||||
{
|
||||
UObject* CDO = BP->GeneratedClass->GetDefaultObject();
|
||||
FProperty* Prop = BP->GeneratedClass->FindPropertyByName(Desc->VarName);
|
||||
if (CDO && Prop)
|
||||
DefaultValueProp = FWingProperty(Prop, CDO);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +48,7 @@ void FWingBlueprintVar::Dump()
|
||||
{
|
||||
LoadFlags();
|
||||
LoadDefault();
|
||||
LoadDelegateArgs();
|
||||
TArray<FWingProperty> Props = MergedProperties();
|
||||
for (FWingProperty& P : Props)
|
||||
{
|
||||
@@ -38,6 +62,7 @@ void FWingBlueprintVar::Dump()
|
||||
bool FWingBlueprintVar::ApplyJson(const FJsonObject* Json)
|
||||
{
|
||||
bool bHasDefault = Json->HasField(TEXT("DefaultValue"));
|
||||
bool bHasDelegateArgs = Json->HasField(TEXT("DelegateArgs"));
|
||||
bool bHasType = Json->HasField(TEXT("VarType"));
|
||||
if (bHasDefault && bHasType)
|
||||
{
|
||||
@@ -49,6 +74,7 @@ bool FWingBlueprintVar::ApplyJson(const FJsonObject* Json)
|
||||
}
|
||||
|
||||
LoadFlags();
|
||||
LoadDelegateArgs();
|
||||
|
||||
TArray<FWingProperty> Props = MergedProperties();
|
||||
if (!WingJson::PopulateFromJson(Props, Json, true))
|
||||
@@ -56,7 +82,9 @@ bool FWingBlueprintVar::ApplyJson(const FJsonObject* Json)
|
||||
|
||||
SaveFlags();
|
||||
if (bHasDefault)
|
||||
return SaveDefault();
|
||||
if (!SaveDefault()) return false;
|
||||
if (bHasDelegateArgs)
|
||||
if (!SaveDelegateArgs()) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -82,6 +110,18 @@ void FWingBlueprintVar::LoadDefault()
|
||||
DefaultValue.Empty();
|
||||
}
|
||||
|
||||
void FWingBlueprintVar::LoadDelegateArgs()
|
||||
{
|
||||
if (!SigGraph) return;
|
||||
TWeakObjectPtr<UK2Node_EditablePinBase> EntryNode;
|
||||
TWeakObjectPtr<UK2Node_EditablePinBase> ResultNode;
|
||||
FBlueprintEditorUtils::GetEntryAndResultNodes(SigGraph, EntryNode, ResultNode);
|
||||
if (EntryNode.IsValid())
|
||||
DelegateArgs = WingFunctionArgs::GetArgs(EntryNode.Get());
|
||||
else
|
||||
DelegateArgs.Empty();
|
||||
}
|
||||
|
||||
void FWingBlueprintVar::SaveFlags()
|
||||
{
|
||||
// CPF flags
|
||||
@@ -125,6 +165,20 @@ bool FWingBlueprintVar::SaveDefault()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FWingBlueprintVar::SaveDelegateArgs()
|
||||
{
|
||||
if (!SigGraph) return true;
|
||||
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 false;
|
||||
}
|
||||
return WingFunctionArgs::SetArgs(EntryNode.Get(), DelegateArgs);
|
||||
}
|
||||
|
||||
TArray<FWingProperty> FWingBlueprintVar::MergedProperties()
|
||||
{
|
||||
TArray<FWingProperty> Props = FWingProperty::GetAll(
|
||||
@@ -139,9 +193,20 @@ TArray<FWingProperty> FWingBlueprintVar::MergedProperties()
|
||||
Props.Append(FWingProperty::GetAll(
|
||||
FWingBlueprintVar::StaticStruct(), this, (EPropertyFlags)0));
|
||||
|
||||
// Remove DefaultValue if we don't have a CDO property to back it.
|
||||
if (!DefaultValueProp)
|
||||
if (SigGraph)
|
||||
{
|
||||
FWingProperty::Remove(Props, TEXT("VarType"));
|
||||
FWingProperty::Remove(Props, TEXT("DefaultValue"));
|
||||
FWingProperty::Remove(Props, TEXT("ExposeOnSpawn"));
|
||||
FWingProperty::Remove(Props, TEXT("ExposeToCinematics"));
|
||||
}
|
||||
else
|
||||
{
|
||||
FWingProperty::Remove(Props, TEXT("DelegateArgs"));
|
||||
// Remove DefaultValue if we don't have a CDO property to back it.
|
||||
if (!DefaultValueProp)
|
||||
FWingProperty::Remove(Props, TEXT("DefaultValue"));
|
||||
}
|
||||
|
||||
return Props;
|
||||
}
|
||||
|
||||
@@ -16,11 +16,13 @@ struct FWingBlueprintVar
|
||||
|
||||
FBPVariableDescription* Desc = nullptr;
|
||||
FWingProperty DefaultValueProp;
|
||||
UEdGraph* SigGraph = nullptr;
|
||||
|
||||
FWingBlueprintVar() = default;
|
||||
FWingBlueprintVar(UBlueprint* BP, const FString& VarName);
|
||||
|
||||
bool NotFound() const { return Desc == nullptr; }
|
||||
bool IsEventDispatcher() const { return SigGraph != nullptr; }
|
||||
|
||||
UPROPERTY(EditAnywhere, meta=(Optional, Description="Default value in Unreal text format"))
|
||||
FString DefaultValue;
|
||||
@@ -43,6 +45,9 @@ struct FWingBlueprintVar
|
||||
UPROPERTY(EditAnywhere, meta=(Optional, Description="Expose to cinematics/sequencer"))
|
||||
bool ExposeToCinematics = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, meta=(Optional, Description="Delegate parameters, e.g. 'int x,float y'"))
|
||||
FString DelegateArgs;
|
||||
|
||||
// Load from Desc, populate from JSON, save back to Desc.
|
||||
bool ApplyJson(const FJsonObject* Json);
|
||||
|
||||
@@ -52,7 +57,9 @@ struct FWingBlueprintVar
|
||||
private:
|
||||
void LoadFlags();
|
||||
void LoadDefault();
|
||||
void LoadDelegateArgs();
|
||||
void SaveFlags();
|
||||
bool SaveDefault();
|
||||
bool SaveDelegateArgs();
|
||||
TArray<FWingProperty> MergedProperties();
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user