// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. #include "BlueprintGraphPrivatePCH.h" #include "BlueprintEventNodeSpawner.h" #include "EdGraphSchema_K2.h" // for GetFriendlySignitureName() #define LOCTEXT_NAMESPACE "BlueprintEventNodeSpawner" /******************************************************************************* * Static UBlueprintEventNodeSpawner Helpers ******************************************************************************/ namespace UBlueprintEventNodeSpawnerImpl { /** * Helper function for scanning a blueprint for a certain, custom named, * event. * * @param Blueprint The blueprint you want to look through * @param CustomName The event name you want to check for. * @return Null if no event was found, otherwise a pointer to the named event. */ static UK2Node_Event* FindCustomEventNode(UBlueprint* Blueprint, FName const CustomName); } //------------------------------------------------------------------------------ UK2Node_Event* UBlueprintEventNodeSpawnerImpl::FindCustomEventNode(UBlueprint* Blueprint, FName const CustomName) { UK2Node_Event* FoundNode = nullptr; if (CustomName != NAME_None) { TArray AllEvents; FBlueprintEditorUtils::GetAllNodesOfClass(Blueprint, AllEvents); for (UK2Node_Event* EventNode : AllEvents) { if (EventNode->CustomFunctionName == CustomName) { FoundNode = EventNode; break; } } } return FoundNode; } /******************************************************************************* * UBlueprintEventNodeSpawner ******************************************************************************/ //------------------------------------------------------------------------------ UBlueprintEventNodeSpawner* UBlueprintEventNodeSpawner::Create(UFunction const* const EventFunc, UObject* Outer/* = nullptr*/) { check(EventFunc != nullptr); if (Outer == nullptr) { Outer = GetTransientPackage(); } UBlueprintEventNodeSpawner* NodeSpawner = NewObject(Outer); NodeSpawner->EventFunc = EventFunc; NodeSpawner->NodeClass = UK2Node_Event::StaticClass(); return NodeSpawner; } //------------------------------------------------------------------------------ UBlueprintEventNodeSpawner* UBlueprintEventNodeSpawner::Create(TSubclassOf NodeClass, FName CustomEventName, UObject* Outer/* = nullptr*/) { if (Outer == nullptr) { Outer = GetTransientPackage(); } UBlueprintEventNodeSpawner* NodeSpawner = NewObject(Outer); NodeSpawner->NodeClass = NodeClass; NodeSpawner->CustomEventName = CustomEventName; return NodeSpawner; } //------------------------------------------------------------------------------ UBlueprintEventNodeSpawner::UBlueprintEventNodeSpawner(class FPostConstructInitializeProperties const& PCIP) : Super(PCIP) , EventFunc(nullptr) { } //------------------------------------------------------------------------------ UEdGraphNode* UBlueprintEventNodeSpawner::Invoke(UEdGraph* ParentGraph, FVector2D const Location) const { check(ParentGraph != nullptr); UBlueprint* Blueprint = FBlueprintEditorUtils::FindBlueprintForGraphChecked(ParentGraph); UK2Node_Event* EventNode = nullptr; FName EventName = CustomEventName; if (EventFunc != nullptr) { check(EventFunc != nullptr); EventName = EventFunc->GetFName(); } UClass* ClassOwner = Blueprint->GeneratedClass; // look to see if a node for this event already exists (only one node is // allowed per event, per blueprint) if (EventFunc != nullptr) { ClassOwner = CastChecked(EventFunc->GetOuter()); EventNode = FBlueprintEditorUtils::FindOverrideForFunction(Blueprint, ClassOwner, EventName); } else { EventNode = UBlueprintEventNodeSpawnerImpl::FindCustomEventNode(Blueprint, EventName); } // if there is no existing node, then we can happily spawn one into the graph if (EventNode == nullptr) { auto PostSpawnLambda = [](UEdGraphNode* NewNode, bool bIsTemplateNode, UFunction const* EventFunc, FName EventName, FCustomizeNodeDelegate UserDelegate) { UK2Node_Event* EventNode = CastChecked(NewNode); if (EventFunc != nullptr) { EventNode->EventSignatureName = EventName; EventNode->EventSignatureClass = EventFunc->GetOuterUClass(); EventNode->bOverrideFunction = true; } else if (!bIsTemplateNode) { EventNode->CustomFunctionName = EventName; } UserDelegate.ExecuteIfBound(NewNode, bIsTemplateNode); }; FCustomizeNodeDelegate PostSpawnDelegate = FCustomizeNodeDelegate::CreateStatic(PostSpawnLambda, EventFunc, EventName, CustomizeNodeDelegate); EventNode = Cast(Super::Invoke(ParentGraph, Location, PostSpawnDelegate)); } // else, a node for this event already exists, and we should return that // (the FBlueprintActionMenuItem should detect this and focus in on it). return EventNode; } //------------------------------------------------------------------------------ FText UBlueprintEventNodeSpawner::GetDefaultMenuName() const { FText EventName; if (EventFunc != nullptr) { EventName = FText::FromString(UEdGraphSchema_K2::GetFriendlySignitureName(EventFunc)); } else if (!CustomEventName.IsNone()) { EventName = FText::FromName(CustomEventName); } if (!EventName.IsEmpty()) { EventName = FText::Format(LOCTEXT("EventWithSignatureName", "Event {0}"), EventName); } return EventName; } //------------------------------------------------------------------------------ FText UBlueprintEventNodeSpawner::GetDefaultSearchKeywords() const { FText Keywords = FText::GetEmpty(); if (EventFunc != nullptr) { Keywords = FText::FromString(UK2Node_CallFunction::GetKeywordsForFunction(EventFunc)); } return Keywords; } //------------------------------------------------------------------------------ UFunction const* UBlueprintEventNodeSpawner::GetEventFunction() const { return EventFunc; } #undef LOCTEXT_NAMESPACE