From e49315503504cccb794b644a07742cb2e883f02d Mon Sep 17 00:00:00 2001 From: jyelon Date: Sat, 21 Mar 2026 00:34:51 -0400 Subject: [PATCH] BlueprintGraph_Create --- .../HalfBaked/BlueprintGraph_Create.h | 116 ----------------- .../Handlers/BlueprintGraph_Create.h | 121 ++++++++++++++++++ .../UEWingman/Private/WingFunctionArgs.cpp | 2 + 3 files changed, 123 insertions(+), 116 deletions(-) delete mode 100644 Plugins/UEWingman/Source/UEWingman/HalfBaked/BlueprintGraph_Create.h create mode 100644 Plugins/UEWingman/Source/UEWingman/Handlers/BlueprintGraph_Create.h diff --git a/Plugins/UEWingman/Source/UEWingman/HalfBaked/BlueprintGraph_Create.h b/Plugins/UEWingman/Source/UEWingman/HalfBaked/BlueprintGraph_Create.h deleted file mode 100644 index 875b069e..00000000 --- a/Plugins/UEWingman/Source/UEWingman/HalfBaked/BlueprintGraph_Create.h +++ /dev/null @@ -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(); - 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(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(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(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)); - } - - } -}; diff --git a/Plugins/UEWingman/Source/UEWingman/Handlers/BlueprintGraph_Create.h b/Plugins/UEWingman/Source/UEWingman/Handlers/BlueprintGraph_Create.h new file mode 100644 index 00000000..afb2c062 --- /dev/null +++ b/Plugins/UEWingman/Source/UEWingman/Handlers/BlueprintGraph_Create.h @@ -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(); + 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(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 Entry; + TWeakObjectPtr 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)); + } +}; diff --git a/Plugins/UEWingman/Source/UEWingman/Private/WingFunctionArgs.cpp b/Plugins/UEWingman/Source/UEWingman/Private/WingFunctionArgs.cpp index abd2d0e7..41204b1d 100644 --- a/Plugins/UEWingman/Source/UEWingman/Private/WingFunctionArgs.cpp +++ b/Plugins/UEWingman/Source/UEWingman/Private/WingFunctionArgs.cpp @@ -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; } +