diff --git a/Plugins/UEWingman/Source/UEWingman/Handlers/ActorComponent_Add.h b/Plugins/UEWingman/Source/UEWingman/Handlers/ActorComponent_Add.h index e8f75117..e7a7e29f 100644 --- a/Plugins/UEWingman/Source/UEWingman/Handlers/ActorComponent_Add.h +++ b/Plugins/UEWingman/Source/UEWingman/Handlers/ActorComponent_Add.h @@ -48,11 +48,9 @@ public: if (!BP) return; // Check that the proposed name is valid - FName InternalID = WingUtils::CheckProposedName(Component, WingOut::Stdout); + TSet InUse = WingUtils::GetAllInUseNames(BP); + FName InternalID = WingUtils::CheckProposedName(Component, InUse, WingOut::Stdout); if (InternalID.IsNone()) return; - TSet Names; - WingUtils::GetAllInUseNames(BP, Names); - if (!WingUtils::FindNoDuplicateName(Names, InternalID, TEXT("variable or component"), WingOut::Stdout)) return; // Resolve the component class by name UWingTypes::Requirements Req; diff --git a/Plugins/UEWingman/Source/UEWingman/Handlers/BlueprintGraph_Add.h b/Plugins/UEWingman/Source/UEWingman/Handlers/BlueprintGraph_Add.h index 1c935568..3f464429 100644 --- a/Plugins/UEWingman/Source/UEWingman/Handlers/BlueprintGraph_Add.h +++ b/Plugins/UEWingman/Source/UEWingman/Handlers/BlueprintGraph_Add.h @@ -73,11 +73,9 @@ public: } // Check graph name uniqueness and legality - FName InternalID = WingUtils::CheckProposedName(Graph, WingOut::Stdout); + TSet InUse = WingUtils::GetAllInUseNames(BP); + FName InternalID = WingUtils::CheckProposedName(Graph, InUse, WingOut::Stdout); if (InternalID.IsNone()) return; - TSet Names; - if (!WingUtils::FindNoDuplicateName(Names, InternalID, TEXT("Graph"), WingOut::Stdout)) return; - if (!WingUtils::FindNoDuplicateNames(Names, WingUtils::AllGraphs(BP), TEXT("Graph"), WingOut::Stdout)) return; // Parse and validate variables before making changes WingVariables Vars; diff --git a/Plugins/UEWingman/Source/UEWingman/Handlers/EventDispatcher_Add.h b/Plugins/UEWingman/Source/UEWingman/Handlers/EventDispatcher_Add.h index 2ebbe952..344510a1 100644 --- a/Plugins/UEWingman/Source/UEWingman/Handlers/EventDispatcher_Add.h +++ b/Plugins/UEWingman/Source/UEWingman/Handlers/EventDispatcher_Add.h @@ -43,11 +43,9 @@ public: if (!BP) return; // Check for valid proposed name - FName InternalID = WingUtils::CheckProposedName(Dispatcher, WingOut::Stdout); + TSet InUse = WingUtils::GetAllInUseNames(BP); + FName InternalID = WingUtils::CheckProposedName(Dispatcher, InUse, WingOut::Stdout); if (InternalID.IsNone()) return; - TSet Names; - WingUtils::GetAllInUseNames(BP, Names); - if (!WingUtils::FindNoDuplicateName(Names, InternalID, TEXT("variable or component"), WingOut::Stdout)) return; // Parse the arguments. WingVariables Vars; diff --git a/Plugins/UEWingman/Source/UEWingman/Handlers/Widget_Add.h b/Plugins/UEWingman/Source/UEWingman/Handlers/Widget_Add.h index c4d9ba47..e003cd92 100644 --- a/Plugins/UEWingman/Source/UEWingman/Handlers/Widget_Add.h +++ b/Plugins/UEWingman/Source/UEWingman/Handlers/Widget_Add.h @@ -66,13 +66,9 @@ public: } // Validate the proposed name. - FName InternalID = WingUtils::CheckProposedName(Name, WingOut::Stdout); + TSet InUse = WingUtils::GetAllInUseNames(BP); + FName InternalID = WingUtils::CheckProposedName(Name, InUse, WingOut::Stdout); if (InternalID.IsNone()) return; - - // Check that the name is unique among existing widgets. - TSet Names; - WingUtils::GetAllInUseNames(BP, Names); - if (!WingUtils::FindNoDuplicateName(Names, InternalID, TEXT("widget or variable"), WingOut::Stdout)) return; // If a parent is specified, find it and verify it's a panel. UPanelWidget* ParentPanel = nullptr; diff --git a/Plugins/UEWingman/Source/UEWingman/Private/WingComponent.cpp b/Plugins/UEWingman/Source/UEWingman/Private/WingComponent.cpp index c6f233c3..52a2a415 100644 --- a/Plugins/UEWingman/Source/UEWingman/Private/WingComponent.cpp +++ b/Plugins/UEWingman/Source/UEWingman/Private/WingComponent.cpp @@ -149,8 +149,7 @@ bool UWingComponent::AddComponent(UBlueprint *BP, UClass *Class, UWingComponentR Errors.Printf(TEXT("This blueprint cannot contain components.\n")); return false; } - TSet Names; - WingUtils::GetAllInUseNames(BP, Names); + TSet Names = WingUtils::GetAllInUseNames(BP); if (Names.Contains(Name)) { Errors.Printf(TEXT("There is already a variable or component named %s in %s.\n"), diff --git a/Plugins/UEWingman/Source/UEWingman/Private/WingUtils.cpp b/Plugins/UEWingman/Source/UEWingman/Private/WingUtils.cpp index 1886069b..8cae4a43 100644 --- a/Plugins/UEWingman/Source/UEWingman/Private/WingUtils.cpp +++ b/Plugins/UEWingman/Source/UEWingman/Private/WingUtils.cpp @@ -61,7 +61,7 @@ FName WingUtils::CheckInternalizeID(const FString &ExternalID, WingOut Errors) return InternalID; } -FName WingUtils::CheckProposedName(const FString &ExternalID, WingOut Errors) +FName WingUtils::CheckProposedName(const FString &ExternalID, const TSet &InUse, WingOut Errors) { FName InternalID = CheckInternalizeID(ExternalID, Errors); if (InternalID.ToString().Len() > 100) @@ -76,6 +76,11 @@ FName WingUtils::CheckProposedName(const FString &ExternalID, WingOut Errors) UWingServer::SuggestManual(WingManual::Section::EscapeSequences); return FName(); } + if (InUse.Contains(InternalID)) + { + Errors.Printf(TEXT("ERROR: id %s is already in use"), *ExternalID); + return FName(); + } return InternalID; } @@ -483,8 +488,9 @@ UObject *WingUtils::GetGeneratedCDO(UBlueprint *BP) return BP->GeneratedClass->GetDefaultObject(); } -void WingUtils::GetAllInUseNames(UBlueprint *BP, TSet &Names) +TSet WingUtils::GetAllInUseNames(UBlueprint *BP) { + TSet Names; FBlueprintEditorUtils::GetClassVariableList(BP, Names, true); FBlueprintEditorUtils::GetFunctionNameList(BP, Names); FBlueprintEditorUtils::GetAllGraphNames(BP, Names); @@ -496,6 +502,7 @@ void WingUtils::GetAllInUseNames(UBlueprint *BP, TSet &Names) WBP->WidgetTree->GetAllWidgets(AllWidgets); WingUtils::AddNamesToSet(Names, AllWidgets); } + return Names; } // ============================================================ diff --git a/Plugins/UEWingman/Source/UEWingman/Private/WingVariables.cpp b/Plugins/UEWingman/Source/UEWingman/Private/WingVariables.cpp index d56c187e..9dbc1902 100644 --- a/Plugins/UEWingman/Source/UEWingman/Private/WingVariables.cpp +++ b/Plugins/UEWingman/Source/UEWingman/Private/WingVariables.cpp @@ -611,9 +611,8 @@ bool WingVariables::CreateBlueprint(WingOut Errors) ClearLinks(); // Check for name collisions against existing variables, components, and the like. - TSet Names; - WingUtils::GetAllInUseNames(Blueprint.Get(), Names); - if (!WingUtils::FindNoDuplicateNames(Names, BlueprintVariables.Variables, TEXT("variable or component"), Errors)) return false; + TSet InUse = WingUtils::GetAllInUseNames(Blueprint.Get()); + if (!WingUtils::FindNoDuplicateNames(InUse, BlueprintVariables.Variables, TEXT("variable or component"), Errors)) return false; // Create the variables. for (const WingVariables::Var& V : BlueprintVariables.Variables) diff --git a/Plugins/UEWingman/Source/UEWingman/Public/WingUtils.h b/Plugins/UEWingman/Source/UEWingman/Public/WingUtils.h index 5f87a321..db7c3e43 100644 --- a/Plugins/UEWingman/Source/UEWingman/Public/WingUtils.h +++ b/Plugins/UEWingman/Source/UEWingman/Public/WingUtils.h @@ -218,13 +218,14 @@ public: // This routine is used when the LLM is proposing a new // name in order to create a new graph, new node, or // something like that. This verifies that the name is - // a valid external ID, it converts it to an internal ID, - // and it also verifies that it's a readable internal ID. - // If anything goes wrong, it prints an error and returns - // empty string. + // a valid external ID, it converts it to an internal + // ID, and it also verifies that it's a readable + // internal ID, and that it is not already in use. + // If anything goes wrong, it prints an error and + // returns empty string. //////////////////////////////////////////////////////// - static FName CheckProposedName(const FString &Name, WingOut Errors); + static FName CheckProposedName(const FString &Name, const TSet &InUse, WingOut Errors); static FString FormatNodeTitle(const UEdGraphNode *Node); @@ -250,7 +251,7 @@ public: static TArray AllNodes(UEdGraph *Graph); static TArray GetAncestorBlueprints(UBlueprint *BP, bool OldestFirst = false); static UObject *GetGeneratedCDO(UBlueprint *BP); - static void GetAllInUseNames(UBlueprint *BP, TSet &Names); + static TSet GetAllInUseNames(UBlueprint *BP); // ----- Graph pin helpers ----- static UEdGraphPin* CheckGetPin(UEdGraphNode* Node, FName PinName, WingOut Errors);