BlueprintGraph_Create
This commit is contained in:
@@ -1,116 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "WingServer.h"
|
||||
#include "WingHandler.h"
|
||||
#include "WingFetcher.h"
|
||||
#include "WingUtils.h"
|
||||
#include "Engine/Blueprint.h"
|
||||
#include "EdGraph/EdGraph.h"
|
||||
#include "EdGraph/EdGraphNode.h"
|
||||
#include "EdGraphSchema_K2.h"
|
||||
#include "K2Node_CustomEvent.h"
|
||||
#include "Kismet2/BlueprintEditorUtils.h"
|
||||
#include "BlueprintGraph_Create.generated.h"
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// ---------------------------------------------------------------------------
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_BlueprintGraph_Create : public UObject, public IWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY(meta=(Description="Blueprint name or package path"))
|
||||
FString Blueprint;
|
||||
|
||||
UPROPERTY(meta=(Description="Name for the new graph"))
|
||||
FString Graph;
|
||||
|
||||
UPROPERTY(meta=(Description="Type of graph: function, macro, or customEvent"))
|
||||
FString GraphType;
|
||||
|
||||
virtual FString GetDescription() const override
|
||||
{
|
||||
return TEXT("Create a new function, macro, or custom event graph in a Blueprint.");
|
||||
}
|
||||
|
||||
virtual void Handle() override
|
||||
{
|
||||
if (GraphType != TEXT("function") && GraphType != TEXT("macro") && GraphType != TEXT("customEvent"))
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Invalid GraphType '%s'. Valid values: function, macro, customEvent\n"), *GraphType);
|
||||
return;
|
||||
}
|
||||
|
||||
WingFetcher F;
|
||||
UBlueprint* BP = F.Walk(Blueprint).Cast<UBlueprint>();
|
||||
if (!BP) return;
|
||||
|
||||
// Check graph name uniqueness
|
||||
if (!WingUtils::FindExactlyNoneNamed(Graph, WingUtils::AllGraphs(BP), TEXT("Graph")))
|
||||
return;
|
||||
|
||||
// For custom events, also check for existing custom events with the same name
|
||||
if (GraphType == TEXT("customEvent"))
|
||||
{
|
||||
for (UK2Node_CustomEvent* CE : WingUtils::AllNodes<UK2Node_CustomEvent>(BP))
|
||||
{
|
||||
if (CE->CustomFunctionName == FName(*Graph))
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: A custom event named '%s' already exists in %s\n"), *Graph, *WingUtils::FormatName(BP));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (GraphType == TEXT("function"))
|
||||
{
|
||||
UEdGraph* NewGraph = FBlueprintEditorUtils::CreateNewGraph(BP, FName(*Graph),
|
||||
UEdGraph::StaticClass(), UEdGraphSchema_K2::StaticClass());
|
||||
if (!NewGraph)
|
||||
{
|
||||
UWingServer::Print(TEXT("ERROR: Failed to create function graph\n"));
|
||||
return;
|
||||
}
|
||||
FBlueprintEditorUtils::AddFunctionGraph(BP, NewGraph, /*bIsUserCreated=*/true, /*SignatureFromObject=*/static_cast<UClass*>(nullptr));
|
||||
UWingServer::Printf(TEXT("Created function graph: %s\n"), *WingUtils::FormatName(NewGraph));
|
||||
}
|
||||
else if (GraphType == TEXT("macro"))
|
||||
{
|
||||
UEdGraph* NewGraph = FBlueprintEditorUtils::CreateNewGraph(BP, FName(*Graph),
|
||||
UEdGraph::StaticClass(), UEdGraphSchema_K2::StaticClass());
|
||||
if (!NewGraph)
|
||||
{
|
||||
UWingServer::Print(TEXT("ERROR: Failed to create macro graph\n"));
|
||||
return;
|
||||
}
|
||||
FBlueprintEditorUtils::AddMacroGraph(BP, NewGraph, /*bIsUserCreated=*/true, /*SignatureFromClass=*/nullptr);
|
||||
UWingServer::Printf(TEXT("Created macro graph: %s\n"), *WingUtils::FormatName(NewGraph));
|
||||
}
|
||||
else // customEvent
|
||||
{
|
||||
UEdGraph* EventGraph = nullptr;
|
||||
if (BP->UbergraphPages.Num() > 0)
|
||||
EventGraph = BP->UbergraphPages[0];
|
||||
if (!EventGraph)
|
||||
{
|
||||
UWingServer::Print(TEXT("ERROR: Blueprint has no EventGraph to add a custom event to\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
UK2Node_CustomEvent* NewEvent = NewObject<UK2Node_CustomEvent>(EventGraph);
|
||||
NewEvent->CustomFunctionName = FName(*Graph);
|
||||
NewEvent->bIsEditable = true;
|
||||
EventGraph->AddNode(NewEvent, /*bFromUI=*/false, /*bSelectNewNode=*/false);
|
||||
NewEvent->CreateNewGuid();
|
||||
NewEvent->PostPlacedNewNode();
|
||||
NewEvent->AllocateDefaultPins();
|
||||
UWingServer::Printf(TEXT("Created custom event: %s\n"), *WingUtils::FormatName(NewEvent));
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,121 @@
|
||||
#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 "EdGraph/EdGraph.h"
|
||||
#include "EdGraph/EdGraphNode.h"
|
||||
#include "K2Node_EditablePinBase.h"
|
||||
#include "K2Node_FunctionResult.h"
|
||||
#include "EdGraphSchema_K2.h"
|
||||
#include "Kismet2/BlueprintEditorUtils.h"
|
||||
#include "BlueprintGraph_Create.generated.h"
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// ---------------------------------------------------------------------------
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_BlueprintGraph_Create : public UObject, public IWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY(meta=(Description="Blueprint name or package path"))
|
||||
FString Blueprint;
|
||||
|
||||
UPROPERTY(meta=(Description="Name for the new graph"))
|
||||
FString Graph;
|
||||
|
||||
UPROPERTY(meta=(Description="Type of graph: function or macro"))
|
||||
FString GraphType;
|
||||
|
||||
UPROPERTY(meta=(Description="Arguments expressed as: int x,float y"))
|
||||
FString Arguments;
|
||||
|
||||
UPROPERTY(meta=(Description="Return values expressed as: int x,float y"))
|
||||
FString ReturnValues;
|
||||
|
||||
virtual FString GetDescription() const override
|
||||
{
|
||||
return TEXT("Create a new function or macro graph in a Blueprint.");
|
||||
}
|
||||
|
||||
virtual void Handle() override
|
||||
{
|
||||
if (GraphType != TEXT("function") && GraphType != TEXT("macro"))
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Invalid GraphType '%s'. Valid values: function, macro\n"), *GraphType);
|
||||
return;
|
||||
}
|
||||
|
||||
WingFetcher F;
|
||||
UBlueprint* BP = F.Walk(Blueprint).Cast<UBlueprint>();
|
||||
if (!BP) return;
|
||||
|
||||
// Check that this graph type is valid for this blueprint type
|
||||
if (BP->BlueprintType == BPTYPE_Interface)
|
||||
{
|
||||
UWingServer::Print(TEXT("ERROR: Cannot add graphs to interface blueprints.\n"));
|
||||
return;
|
||||
}
|
||||
if (BP->BlueprintType == BPTYPE_MacroLibrary && GraphType == TEXT("function"))
|
||||
{
|
||||
UWingServer::Print(TEXT("ERROR: Macro libraries cannot contain functions.\n"));
|
||||
return;
|
||||
}
|
||||
if (BP->BlueprintType == BPTYPE_FunctionLibrary && GraphType == TEXT("macro"))
|
||||
{
|
||||
UWingServer::Print(TEXT("ERROR: Function libraries cannot contain macros.\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Check graph name uniqueness and legality
|
||||
if (!WingUtils::FindExactlyNoneNamed(Graph, WingUtils::AllGraphs(BP), TEXT("Graph")))
|
||||
return;
|
||||
FString InternalName = WingUtils::CheckProposedName(Graph);
|
||||
if (InternalName.IsEmpty()) return;
|
||||
|
||||
// Validate argument and return value types before making changes
|
||||
if (!Arguments.IsEmpty() && !WingFunctionArgs::CheckArgs(Arguments)) return;
|
||||
if (!ReturnValues.IsEmpty() && !WingFunctionArgs::CheckArgs(ReturnValues)) return;
|
||||
|
||||
// Create the Graph
|
||||
UEdGraph* NewGraph = FBlueprintEditorUtils::CreateNewGraph(BP, FName(InternalName),
|
||||
UEdGraph::StaticClass(), UEdGraphSchema_K2::StaticClass());
|
||||
if (!NewGraph)
|
||||
{
|
||||
UWingServer::Print(TEXT("ERROR: Failed to create graph\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (GraphType == TEXT("function"))
|
||||
{
|
||||
FBlueprintEditorUtils::AddFunctionGraph(BP, NewGraph, /*bIsUserCreated=*/true, /*SignatureFromObject=*/static_cast<UClass*>(nullptr));
|
||||
FBlueprintEditorUtils::FindOrCreateFunctionResultNode(FBlueprintEditorUtils::GetEntryNode(NewGraph));
|
||||
}
|
||||
else if (GraphType == TEXT("macro"))
|
||||
{
|
||||
FBlueprintEditorUtils::AddMacroGraph(BP, NewGraph, /*bIsUserCreated=*/true, /*SignatureFromClass=*/nullptr);
|
||||
}
|
||||
|
||||
// Try GetEntryAndResultNodes first (works for both functions and macros)
|
||||
TWeakObjectPtr<UK2Node_EditablePinBase> Entry;
|
||||
TWeakObjectPtr<UK2Node_EditablePinBase> Exit;
|
||||
FBlueprintEditorUtils::GetEntryAndResultNodes(NewGraph, Entry, Exit);
|
||||
if ((Entry == nullptr) || (Exit == nullptr))
|
||||
{
|
||||
UWingServer::Printf(TEXT("Could not get graph entry and exit nodes.\n"));
|
||||
return;
|
||||
}
|
||||
if (!WingFunctionArgs::SetArgs(Entry.Get(), Arguments)) return;
|
||||
if (!WingFunctionArgs::SetArgs(Exit.Get(), ReturnValues)) return;
|
||||
|
||||
UWingServer::Printf(TEXT("Created %s graph: %s\n"), *GraphType, *WingUtils::FormatName(NewGraph));
|
||||
}
|
||||
};
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "WingTypes.h"
|
||||
#include "WingUtils.h"
|
||||
#include "WingServer.h"
|
||||
#include "Kismet2/BlueprintEditorUtils.h"
|
||||
|
||||
bool WingFunctionArgs::HasArgs(UEdGraphNode* Node)
|
||||
{
|
||||
@@ -117,3 +118,4 @@ bool WingFunctionArgs::CheckArgs(const FString &Args)
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user