ComboInput/Source/ComboInputEditor/Private/Helpers/ComboActionGraphEditorUtilities.cpp

258 lines
7.5 KiB
C++

// ©2023 Batty Bovine Productions, LLC. All Rights Reserved.
#include "ComboActionGraphEditorUtilities.h"
#include "ComboActionGraph.h"
#include "K2Node_Event.h"
#include "Ed/AssetEditor_ComboActionGraph.h"
#include "Ed/EdComboActionGraph.h"
#include "Ed/EdComboActionGraphNode.h"
#include "Kismet2/BlueprintEditorUtils.h"
#include "Kismet2/KismetEditorUtilities.h"
#include "Kismet2/SClassPickerDialog.h"
#include "Layout/AssetEditorTabs.h"
bool FComboActionGraphEditorUtilities::PickChildrenOfClass(const FText &TitleText, UClass *&OutChosenClass, UClass *Class)
{
// Create filter
TSharedPtr<FComboActionClassViewerFilter> Filter = MakeShareable(new FComboActionClassViewerFilter);
Filter->AllowedChildrenOfClasses.Add(Class);
// Fill in options
FClassViewerInitializationOptions Options;
Options.Mode = EClassViewerMode::ClassPicker;
Options.bShowUnloadedBlueprints = true;
Options.ClassFilters.Add(Filter.ToSharedRef());
Options.DisplayMode = EClassViewerDisplayMode::TreeView;
Options.bShowNoneOption = false;
Options.InitiallySelectedClass = Class;
Options.bExpandRootNodes = true;
Options.NameTypeToDisplay = EClassViewerNameTypeToDisplay::DisplayName;
return SClassPickerDialog::PickClass(TitleText, Options, OutChosenClass, Class);
}
bool FComboActionGraphEditorUtilities::OpenBlueprintEditor(UBlueprint *Blueprint, EComboActionBlueprintOpenType OpenType, FName FunctionNameToOpen, bool bForceFullEditor, bool bAddBlueprintFunctionIfItDoesNotExist)
{
if (!Blueprint)
{
return false;
}
Blueprint->bForceFullEditor = bForceFullEditor;
// Find Function Graph
UObject *ObjectToFocusOn = nullptr;
if (OpenType != EComboActionBlueprintOpenType::None && FunctionNameToOpen != NAME_None)
{
UClass* Class = Blueprint->GeneratedClass;
check(Class);
if (OpenType == EComboActionBlueprintOpenType::Function)
{
ObjectToFocusOn = bAddBlueprintFunctionIfItDoesNotExist
? FComboActionGraphEditorUtilities::BlueprintGetOrAddFunction(Blueprint, FunctionNameToOpen, Class)
: FComboActionGraphEditorUtilities::BlueprintGetFunction(Blueprint, FunctionNameToOpen, Class);
}
else if (OpenType == EComboActionBlueprintOpenType::Event)
{
ObjectToFocusOn = bAddBlueprintFunctionIfItDoesNotExist
? FComboActionGraphEditorUtilities::BlueprintGetOrAddEvent(Blueprint, FunctionNameToOpen, Class)
: FComboActionGraphEditorUtilities::BlueprintGetEvent(Blueprint, FunctionNameToOpen, Class);
}
}
// Default to the last uber graph
if (ObjectToFocusOn == nullptr)
{
ObjectToFocusOn = Blueprint->GetLastEditedUberGraph();
}
if (ObjectToFocusOn)
{
FKismetEditorUtilities::BringKismetToFocusAttentionOnObject(ObjectToFocusOn);
return true;
}
return FComboActionGraphEditorUtilities::OpenEditorForAsset(Blueprint);
}
UEdGraph *FComboActionGraphEditorUtilities::BlueprintGetOrAddFunction(UBlueprint *Blueprint, FName FunctionName, UClass *FunctionClassSignature)
{
if (!Blueprint || Blueprint->BlueprintType != BPTYPE_Normal)
{
return nullptr;
}
// Find existing function
if (UEdGraph *GraphFunction = BlueprintGetFunction(Blueprint, FunctionName, FunctionClassSignature))
{
return GraphFunction;
}
// Create a new function
UEdGraph *NewGraph = FBlueprintEditorUtils::CreateNewGraph(Blueprint, FunctionName, UEdGraph::StaticClass(), UEdGraphSchema_K2::StaticClass());
FBlueprintEditorUtils::AddFunctionGraph(Blueprint, NewGraph, /*bIsUserCreated=*/ false, FunctionClassSignature);
Blueprint->LastEditedDocuments.Add(NewGraph);
return NewGraph;
}
UEdGraph *FComboActionGraphEditorUtilities::BlueprintGetFunction(UBlueprint *Blueprint, FName FunctionName, UClass *FunctionClassSignature)
{
if (!Blueprint || Blueprint->BlueprintType != BPTYPE_Normal)
{
return nullptr;
}
// Find existing function
for (UEdGraph *GraphFunction : Blueprint->FunctionGraphs)
{
if (FunctionName == GraphFunction->GetFName())
{
return GraphFunction;
}
}
// Find in the implemented Interfaces Graphs
for (const FBPInterfaceDescription &Interface : Blueprint->ImplementedInterfaces)
{
for (UEdGraph *GraphFunction : Interface.Graphs)
{
if (FunctionName == GraphFunction->GetFName())
{
return GraphFunction;
}
}
}
return nullptr;
}
UK2Node_Event *FComboActionGraphEditorUtilities::BlueprintGetOrAddEvent(UBlueprint *Blueprint, FName EventName, UClass *EventClassSignature)
{
if (!Blueprint || Blueprint->BlueprintType != EBlueprintType::BPTYPE_Normal)
{
return nullptr;
}
// Find existing event
if (UK2Node_Event *EventNode = FComboActionGraphEditorUtilities::BlueprintGetEvent(Blueprint, EventName, EventClassSignature))
{
return EventNode;
}
// Create a New Event
if (Blueprint->UbergraphPages.Num())
{
int32 NodePositionY = 0;
UK2Node_Event* NodeEvent = FKismetEditorUtilities::AddDefaultEventNode(
Blueprint,
Blueprint->UbergraphPages[0],
EventName,
EventClassSignature,
NodePositionY
);
NodeEvent->SetEnabledState(ENodeEnabledState::Enabled);
NodeEvent->NodeComment = "";
NodeEvent->bCommentBubbleVisible = false;
return NodeEvent;
}
return nullptr;
}
UK2Node_Event *FComboActionGraphEditorUtilities::BlueprintGetEvent(UBlueprint *Blueprint, FName EventName, UClass *EventClassSignature)
{
if (!Blueprint || Blueprint->BlueprintType != EBlueprintType::BPTYPE_Normal)
{
return nullptr;
}
TArray<UK2Node_Event*> AllEvents;
FBlueprintEditorUtils::GetAllNodesOfClass<UK2Node_Event>(Blueprint, AllEvents);
for (UK2Node_Event *EventNode : AllEvents)
{
if (EventNode->bOverrideFunction && EventNode->EventReference.GetMemberName() == EventName)
{
return EventNode;
}
}
return nullptr;
}
bool FComboActionGraphEditorUtilities::OpenEditorForAsset(const UObject* Asset)
{
if (!IsValid(Asset) || !GEditor)
{
return false;
}
return GEditor->GetEditorSubsystem<UAssetEditorSubsystem>()->OpenEditorForAsset(const_cast<UObject*>(Asset));
}
bool FComboActionGraphEditorUtilities::OpenEditorAndJumpToGraphNode(TWeakPtr<FAssetEditor_ComboActionGraph> DialogueEditorPtr, const UEdGraphNode *GraphNode, bool bFocusIfOpen)
{
if (!IsValid(GraphNode))
{
return false;
}
if (!DialogueEditorPtr.IsValid())
{
return false;
}
// Open if not already.
UComboActionGraph *Dialogue = FComboActionGraphEditorUtilities::GetActionFromGraphNode(GraphNode);
if (!FComboActionGraphEditorUtilities::OpenEditorForAsset(Dialogue))
{
return false;
}
// Could still fail focus on the graph node
if (IAssetEditorInstance *EditorInstance = FindEditorForAsset(Dialogue, bFocusIfOpen))
{
EditorInstance->FocusWindow(const_cast<UEdGraphNode*>(GraphNode));
UEdComboActionGraph *GraphEditor = Cast<UEdComboActionGraph>(Dialogue->EdGraph);
if (GraphEditor)
{
TSet<const UEdGraphNode*> SelectedNodes;
SelectedNodes.Add(GraphNode);
GraphEditor->SelectNodeSet(SelectedNodes);
DialogueEditorPtr.Pin()->JumpToNode(GraphNode);
}
return true;
}
return false;
}
UComboActionGraph *FComboActionGraphEditorUtilities::GetActionFromGraphNode(const UEdGraphNode *GraphNode)
{
if (const UEdComboActionGraphNode *ComboActionBaseNode = Cast<UEdComboActionGraphNode>(GraphNode))
{
return ComboActionBaseNode->GetEdComboActionGraph()->GetComboActionGraph();
}
if (const UEdComboActionGraph *ComboActionGraph = Cast<UEdComboActionGraph>(GraphNode->GetGraph()))
{
return Cast<UComboActionGraph>(ComboActionGraph->GetComboActionGraph());
}
return nullptr;
}
IAssetEditorInstance *FComboActionGraphEditorUtilities::FindEditorForAsset(UObject* Asset, bool bFocusIfOpen)
{
if (!IsValid(Asset) || !GEditor)
{
return nullptr;
}
return GEditor->GetEditorSubsystem<UAssetEditorSubsystem>()->FindEditorForAsset(Asset, bFocusIfOpen);
}