Added a bunch more stuff. Too much to care to mention. Still more to do though.
This commit is contained in:
@@ -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);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user