Added a bunch more stuff. Too much to care to mention. Still more to do though.

This commit is contained in:
Jamie Greunbaum
2023-09-30 01:25:51 -04:00
parent cfe285b94d
commit 102927a690
60 changed files with 1664 additions and 76 deletions
@@ -0,0 +1,257 @@
// ©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);
}
@@ -0,0 +1,103 @@
// ©2023 Batty Bovine Productions, LLC. All Rights Reserved.
#pragma once
#include "ClassViewerFilter.h"
enum class EComboActionBlueprintOpenType : uint8
{
None = 0,
Function,
Event
};
class FComboActionClassViewerFilter : public IClassViewerFilter
{
public:
// All children of these classes will be included unless filtered out by another setting.
TSet<const UClass*> AllowedChildrenOfClasses;
virtual bool IsClassAllowed(const FClassViewerInitializationOptions &InInitOptions, const UClass *InClass, TSharedRef<FClassViewerFilterFuncs> InFilterFuncs) override
{
return !InClass->HasAnyClassFlags(this->DisallowedClassFlags)
&& InFilterFuncs->IfInChildOfClassesSet(this->AllowedChildrenOfClasses, InClass) != EFilterReturn::Failed;
}
virtual bool IsUnloadedClassAllowed(const FClassViewerInitializationOptions &InInitOptions, const TSharedRef<const IUnloadedBlueprintData> InUnloadedClassData, TSharedRef<FClassViewerFilterFuncs> InFilterFuncs) override
{
return !InUnloadedClassData->HasAnyClassFlags(this->DisallowedClassFlags)
&& InFilterFuncs->IfInChildOfClassesSet(this->AllowedChildrenOfClasses, InUnloadedClassData) != EFilterReturn::Failed;
}
private:
// Disallowed class flags.
EClassFlags DisallowedClassFlags = CLASS_Deprecated;
};
class FComboActionGraphEditorUtilities
{
public:
static bool PickChildrenOfClass(const FText &TitleText, UClass *&OutChosenClass, UClass *Class);
static bool OpenBlueprintEditor
(
UBlueprint *Blueprint,
EComboActionBlueprintOpenType OpenType = EComboActionBlueprintOpenType::None,
FName FunctionNameToOpen = NAME_None,
bool bForceFullEditor = true,
bool bAddBlueprintFunctionIfItDoesNotExist = false
);
static UEdGraph *BlueprintGetOrAddFunction(UBlueprint *Blueprint, FName FunctionName, UClass *FunctionClassSignature);
static UEdGraph *BlueprintGetFunction(UBlueprint *Blueprint, FName FunctionName, UClass *FunctionClassSignature);
static class UK2Node_Event *BlueprintGetOrAddEvent(UBlueprint *Blueprint, FName EventName, UClass *EventClassSignature);
static class UK2Node_Event *BlueprintGetEvent(UBlueprint *Blueprint, FName EventName, UClass *EventClassSignature);
static bool OpenEditorForAsset(const UObject *Asset);
static bool IsABlueprintClass(const UClass *Class) { return Cast<UBlueprintGeneratedClass>(Class) != nullptr; }
static bool GetAllChildClassesOf(const UClass *ParentClass, TArray<UClass*> &OutNativeClasses, TArray<UClass*> &OutBlueprintClasses)
{
// Iterate over UClass, this might be heavy on performance
for (TObjectIterator<UClass> It; It; ++It)
{
UClass *ChildClass = *It;
if (!ChildClass->IsChildOf(ParentClass))
{
continue;
}
// It is a child of the Parent Class
// make sure we don't include our parent class in the array
if (ChildClass == ParentClass)
{
continue;
}
if (FComboActionGraphEditorUtilities::IsABlueprintClass(ChildClass))
{
// Blueprint
OutBlueprintClasses.Add(ChildClass);
}
else
{
// Native
OutNativeClasses.Add(ChildClass);
}
}
return OutNativeClasses.Num() > 0 || OutBlueprintClasses.Num() > 0;
}
static bool OpenEditorAndJumpToGraphNode(TWeakPtr<class FAssetEditor_ComboActionGraph> DialogueEditorPtr, const UEdGraphNode *GraphNode, bool bFocusIfOpen = false);
static class UComboActionGraph *GetActionFromGraphNode(const UEdGraphNode *GraphNode);
static IAssetEditorInstance *FindEditorForAsset(UObject *Asset, bool bFocusIfOpen);
};