ComboActionGraph classes can now be added in the content browser. No asset editor yet though.

This commit is contained in:
Jamie Greunbaum 2023-09-29 01:33:09 -04:00
parent 8b6cfafc45
commit de9865758a
14 changed files with 1492 additions and 62 deletions

View File

@ -28,12 +28,13 @@ public class ComboInputEditor : ModuleRules
"Engine",
"UnrealEd",
"ApplicationCore",
"AssetTools",
"DeveloperSettings",
"GraphEditor",
"Projects",
"Slate",
"SlateCore",
"Projects",
"GraphEditor",
"DeveloperSettings",
"ToolMenus",
}
);

View File

@ -3,7 +3,7 @@
#include "ComboActionGraphSchema.h"
#include "ComboActionGraph.h"
#include "FConnectionDrawingPolicy_ComboActionGraph.h"
//#include "FConnectionDrawingPolicy_ComboActionGraph.h"
#include "GraphEditorActions.h"
#include "Ed/EdComboActionGraphEdge.h"
@ -365,7 +365,8 @@ FConnectionDrawingPolicy *UComboActionGraphSchema::CreateConnectionDrawingPolicy
}
*/
return new FConnectionDrawingPolicy_ComboActionGraph(InBackLayerID, InFrontLayerID, InZoomFactor, InClippingRect, InDrawElements, InGraphObj);
//return new FConnectionDrawingPolicy_ComboActionGraph(InBackLayerID, InFrontLayerID, InZoomFactor, InClippingRect, InDrawElements, InGraphObj);
return nullptr;
}
FLinearColor UComboActionGraphSchema::GetPinTypeColor(const FEdGraphPinType& PinType) const

View File

@ -2,10 +2,15 @@
#include "ComboInputEditor.h"
#include "ComboActionGraph.h"
#include "ComboInputAssets.h"
#include "ToolMenuSection.h"
#include "AssetTypeActions/AssetTypeActions_DataAsset.h"
#include "Ed/EdComboActionGraphEdge.h"
#include "Ed/EdComboActionGraphNode.h"
#include "Ed/SEdComboActionGraphEdge.h"
#include "Ed/SEdComboActionGraphNode.h"
#include "Interfaces/IPluginManager.h"
#include "Settings/FComboActionGraphEditorStyle.h"
#include "Styling/SlateStyle.h"
@ -17,6 +22,7 @@
#define LOCTEXT_NAMESPACE "FComboInputEditorModule"
EAssetTypeCategories::Type FComboInputEditorModule::ComboAssetsCategory;
EAssetTypeCategories::Type FComboInputEditorModule::ComboActionGraphCategory;
class FAssetTypeActions_ComboAction : public FAssetTypeActions_DataAsset
@ -49,26 +55,66 @@ public:
virtual UClass *GetSupportedClass() const override { return UComboInputAsset::StaticClass(); }
};
class FAssetTypeActions_ComboActionGraph : public FAssetTypeActions_Base
{
public:
virtual FText GetName() const override { return NSLOCTEXT("AssetTypeActions", "AssetTypeActions_ComboActionGraph", "Combo Action Graph"); }
virtual uint32 GetCategories() override { return FComboInputEditorModule::GetInputAssetsCategory(); }
virtual FColor GetTypeColor() const override { return FColor(255, 127, 255); }
virtual FText GetAssetDescription(const FAssetData &AssetData) const override { return NSLOCTEXT("AssetTypeActions", "AssetTypeActions_ComboActionGraphDesc", "This maps a sequence of button inputs from EnhancedInput to a combo action that can be used to execute a sequence of moves. This gets sent from the input buffer subsystem to the player controller's ComboManagerComponent, which executes the associated action in the current ComboSequenceNode."); }
virtual UClass *GetSupportedClass() const override { return UComboActionGraph::StaticClass(); }
virtual void OpenAssetEditor(const TArray<UObject*> &InObjects, TSharedPtr<class IToolkitHost> EditWithinLevelEditor = TSharedPtr<IToolkitHost>()) override
{
//const EToolkitMode::Type Mode = EditWithinLevelEditor.IsValid() ? EToolkitMode::WorldCentric : EToolkitMode::Standalone;
//for (auto ObjIt = InObjects.CreateConstIterator(); ObjIt; ObjIt++)
//{
// if (UComboActionGraph *Graph = Cast<UComboActionGraph>(*ObjIt))
// {
// TSharedRef<FAssetEditor_ComboActionGraph> NewGraphEditor(new FAssetEditor_ComboActionGraph());
// NewGraphEditor->InitMounteaDialogueGraphAssetEditor(Mode, EditWithinLevelEditor, Graph);
// }
//}
}
};
class FComboActionGraphPanelNodeFactory : public FGraphPanelNodeFactory
{
public:
virtual TSharedPtr<class SGraphNode> CreateNode(UEdGraphNode *Node) const override
{
if (UEdComboActionGraphNode *EdGraphNode = Cast<UEdComboActionGraphNode>(Node))
{
return SNew(SEdComboActionGraphNode, EdGraphNode);
}
else if (UEdComboActionGraphEdge *EdGraphEdge = Cast<UEdComboActionGraphEdge>(Node))
{
return SNew(SEdComboActionGraphEdge, EdGraphEdge);
}
return nullptr;
}
};
UComboAction_Factory::UComboAction_Factory(const FObjectInitializer &ObjectInitializer)
: Super(ObjectInitializer)
{
SupportedClass = UComboAction::StaticClass();
bEditAfterNew = true;
bCreateNew = true;
this->SupportedClass = UComboAction::StaticClass();
this->bEditAfterNew = true;
this->bCreateNew = true;
}
UObject *UComboAction_Factory::FactoryCreateNew(UClass *Class, UObject *InParent, FName Name, EObjectFlags Flags, UObject *Context, FFeedbackContext *Warn)
{
if (this->ComboActionClass != nullptr)
{
return NewObject<UComboAction>(InParent, this->ComboActionClass, Name, Flags | RF_Transactional, Context);
return NewObject<UComboAction>(InParent, this->ComboActionClass, Name, Flags | EObjectFlags::RF_Transactional, Context);
}
else
{
check(Class->IsChildOf(UComboAction::StaticClass()));
return NewObject<UComboAction>(InParent, Class, Name, Flags | RF_Transactional, Context);
return NewObject<UComboAction>(InParent, Class, Name, Flags | EObjectFlags::RF_Transactional, Context);
}
}
@ -76,21 +122,21 @@ UObject *UComboAction_Factory::FactoryCreateNew(UClass *Class, UObject *InParent
UComboSequenceNode_Factory::UComboSequenceNode_Factory(const FObjectInitializer &ObjectInitializer)
: Super(ObjectInitializer)
{
SupportedClass = UComboSequenceNode::StaticClass();
bEditAfterNew = true;
bCreateNew = true;
this->SupportedClass = UComboSequenceNode::StaticClass();
this->bEditAfterNew = true;
this->bCreateNew = true;
}
UObject *UComboSequenceNode_Factory::FactoryCreateNew(UClass *Class, UObject *InParent, FName Name, EObjectFlags Flags, UObject *Context, FFeedbackContext *Warn)
{
if (this->ComboSequenceNodeClass != nullptr)
{
return NewObject<UComboSequenceNode>(InParent, this->ComboSequenceNodeClass, Name, Flags | RF_Transactional, Context);
return NewObject<UComboSequenceNode>(InParent, this->ComboSequenceNodeClass, Name, Flags | EObjectFlags::RF_Transactional, Context);
}
else
{
check(Class->IsChildOf(UComboSequenceNode::StaticClass()));
return NewObject<UComboSequenceNode>(InParent, Class, Name, Flags | RF_Transactional, Context);
return NewObject<UComboSequenceNode>(InParent, Class, Name, Flags | EObjectFlags::RF_Transactional, Context);
}
}
@ -98,25 +144,46 @@ UObject *UComboSequenceNode_Factory::FactoryCreateNew(UClass *Class, UObject *In
UComboInputAsset_Factory::UComboInputAsset_Factory(const FObjectInitializer &ObjectInitializer)
: Super(ObjectInitializer)
{
SupportedClass = UComboInputAsset::StaticClass();
bEditAfterNew = true;
bCreateNew = true;
this->SupportedClass = UComboInputAsset::StaticClass();
this->bEditAfterNew = true;
this->bCreateNew = true;
}
UObject *UComboInputAsset_Factory::FactoryCreateNew(UClass *Class, UObject *InParent, FName Name, EObjectFlags Flags, UObject *Context, FFeedbackContext *Warn)
{
if (this->ComboInputAssetClass != nullptr)
{
return NewObject<UComboInputAsset>(InParent, this->ComboInputAssetClass, Name, Flags | RF_Transactional, Context);
return NewObject<UComboInputAsset>(InParent, this->ComboInputAssetClass, Name, Flags | EObjectFlags::RF_Transactional, Context);
}
else
{
check(Class->IsChildOf(UComboInputAsset::StaticClass()));
return NewObject<UComboInputAsset>(InParent, Class, Name, Flags | RF_Transactional, Context);
return NewObject<UComboInputAsset>(InParent, Class, Name, Flags | EObjectFlags::RF_Transactional, Context);
}
}
UComboActionGraph_Factory::UComboActionGraph_Factory(const FObjectInitializer &ObjectInitializer)
: Super(ObjectInitializer)
{
this->SupportedClass = UComboActionGraph::StaticClass();
this->bEditAfterNew = true;
this->bCreateNew = true;
}
UObject *UComboActionGraph_Factory::FactoryCreateNew(UClass *Class, UObject *InParent, FName Name, EObjectFlags Flags, UObject *Context, FFeedbackContext *Warn)
{
if (this->ComboActionGraphClass != nullptr)
{
return NewObject<UComboActionGraph>(InParent, this->ComboActionGraphClass, Name, Flags | EObjectFlags::RF_Transactional, Context);
}
else
{
check(Class->IsChildOf(UComboActionGraph::StaticClass()));
return NewObject<UComboActionGraph>(InParent, Class, Name, Flags | EObjectFlags::RF_Transactional, Context);
}
}
class FComboInputSlateStyle final : public FSlateStyleSet
{
@ -149,12 +216,11 @@ public:
};
void FComboInputEditorModule::StartupModule()
{
// Register combo action asset
IAssetTools &AssetTools = FModuleManager::LoadModuleChecked<FAssetToolsModule>("AssetTools").Get();
FComboInputEditorModule::ComboAssetsCategory = AssetTools.RegisterAdvancedAssetCategory(FName(TEXT("Input")), LOCTEXT("InputAssetsCategory", "Input"));
FComboInputEditorModule::ComboAssetsCategory = AssetTools.RegisterAdvancedAssetCategory(FName(TEXT("Combo Input")), LOCTEXT("ComboInputAssetsCategory", "Combo Input"));
this->RegisterAssetTypeActions(AssetTools, MakeShareable(new FAssetTypeActions_ComboAction));
this->RegisterAssetTypeActions(AssetTools, MakeShareable(new FAssetTypeActions_ComboSequenceNode));
this->RegisterAssetTypeActions(AssetTools, MakeShareable(new FAssetTypeActions_ComboInputAsset));
@ -163,13 +229,36 @@ void FComboInputEditorModule::StartupModule()
this->ComboInputEditorStyleSet = MakeShared<FComboInputSlateStyle>();
FSlateStyleRegistry::RegisterSlateStyle(*this->ComboInputEditorStyleSet.Get());
// Combo Action Graph
{
// Make a new style set for Combo Action Graph
this->ComboActionGraphEditorStyleSet = MakeShared<FComboActionGraphEditorStyle>();
FSlateStyleRegistry::RegisterSlateStyle(*this->ComboActionGraphEditorStyleSet.Get());
}
void FComboInputEditorModule::ShutdownModule()
this->ComboActionGraphPanelNodeFactory = MakeShareable(new FComboActionGraphPanelNodeFactory());
FEdGraphUtilities::RegisterVisualNodeFactory(this->ComboActionGraphPanelNodeFactory);
// Register asset actions
this->ComboActionGraphAssetActions = MakeShared<FAssetTypeActions_ComboActionGraph>();
this->RegisterAssetTypeActions(AssetTools, this->ComboActionGraphAssetActions.ToSharedRef());
// Register thumbnails and icons
this->ComboActionGraphStyleSet = MakeShareable(new FSlateStyleSet("ComboActionGraphStyleSet"));
const TSharedPtr<IPlugin> PluginPtr = IPluginManager::Get().FindPlugin("ComboInput");
if (PluginPtr.IsValid())
{
const FString ContentDir = PluginPtr->GetBaseDir();
this->ComboActionGraphStyleSet->SetContentRoot(ContentDir);
FSlateImageBrush *ComboActionGraphStyleSetClassThumb = new FSlateImageBrush(this->ComboActionGraphStyleSet->RootToContentDir(TEXT("Resources/ComboActionGraphIcon_128"), TEXT(".png")), FVector2D(128.0f, 128.0f));
FSlateImageBrush *ComboActionGraphStyleSetClassIcon = new FSlateImageBrush(this->ComboActionGraphStyleSet->RootToContentDir(TEXT("Resources/ComboActionGraphIcon_16"), TEXT(".png")), FVector2D(16.0f, 16.0f));
if (ComboActionGraphStyleSetClassThumb && ComboActionGraphStyleSetClassIcon)
{
this->ComboActionGraphStyleSet->Set("ClassThumbnail.ComboActionGraph", ComboActionGraphStyleSetClassThumb);
this->ComboActionGraphStyleSet->Set("ClassIcon.ComboActionGraph", ComboActionGraphStyleSetClassIcon);
}
FSlateStyleRegistry::RegisterSlateStyle(*this->ComboActionGraphStyleSet.Get());
}
}
}
#undef LOCTEXT_NAMESPACE

View File

@ -0,0 +1,978 @@
// Copyright Dominik Pavlicek 2023. All Rights Reserved.
#include "AssetEditor_ComboActionGraph.h"
#include "GraphEditorActions.h"
#include "Framework/Commands/GenericCommands.h"
#include "Kismet2/BlueprintEditorUtils.h"
#include "HAL/PlatformApplicationMisc.h"
#include "EdGraphUtilities.h"
#include "ComboInputEditor.h"
#include "ComboActionGraph.h"
#include "Nodes/ComboActionGraphNode.h"
//#include "EditorCommands/FComboActionGraphEditorCommands.h"
//#include "AssetEditor/FAssetEditorToolbarComboActionGraph.h"
#include "Ed/EdComboActionGraph.h"
#include "Ed/EdComboActionGraphEdge.h"
#include "Ed/EdComboActionGraphNode.h"
#include "Settings/FComboActionGraphEditorStyle.h"
#include "ComboActionGraphSchema.h"
//#include "Layout/AssetEditorTabs.h"
//#include "Helpers/ComboActionGraphHelpers.h"
//#include "Helpers/ComboActionSystemEditorBFC.h"
//#include "Layout/ForceDirectedSolveLayoutStrategy.h"
//#include "Layout/ComboActionGraphLayoutStrategy.h"
//#include "Layout/TreeSolveLayoutStrategy.h"
//#include "Popups/MDSPopup_GraphValidation.h"
//#include "Search/ComboActionSearchUtils.h"
#include "Settings/ComboActionGraphEditorSettings.h"
#include "UObject/ObjectSaveContext.h"
#define LOCTEXT_NAMESPACE "AssetEditor_ComboActionGraph"
DEFINE_LOG_CATEGORY(LogAssetEditorComboActionGraph);
#pragma region ConstantNames
const FName ComboActionGraphEditorAppName = FName(TEXT("ComboActionGraphEditorApp"));
//const FName FAssetEditorTabs_ComboActionGraph::ComboActionGraphPropertyID(TEXT("ComboActionGraphProperty"));
//const FName FAssetEditorTabs_ComboActionGraph::ViewportID(TEXT("Viewport"));
//const FName FAssetEditorTabs_ComboActionGraph::SearchToolbarID(TEXT("Search"));
#pragma endregion
FAssetEditor_ComboActionGraph::FAssetEditor_ComboActionGraph()
{
this->EditingGraph = nullptr;
this->ComboActionGraphEditorSettings = GetMutableDefault<UComboActionGraphEditorSettings>();
this->OnPackageSavedDelegateHandle = UPackage::PackageSavedWithContextEvent.AddRaw(this, &FAssetEditor_ComboActionGraph::OnPackageSaved);
}
FAssetEditor_ComboActionGraph::~FAssetEditor_ComboActionGraph()
{
this->EditingGraph = nullptr;
UPackage::PackageSavedWithContextEvent.Remove(this->OnPackageSavedDelegateHandle);
//FGenericCommands::Unregister();
//FGraphEditorCommands::Unregister();
//FComboActionGraphEditorCommands::Unregister();
//this->ToolbarBuilder.Reset();
}
void FAssetEditor_ComboActionGraph::OnPackageSaved(const FString& String, UPackage* Package, FObjectPostSaveContext ObjectPostSaveContext)
{
this->RebuildComboActionGraph();
}
void FAssetEditor_ComboActionGraph::InitComboActionGraphAssetEditor(const EToolkitMode::Type Mode, const TSharedPtr<IToolkitHost>& InitToolkitHost, UComboActionGraph *Graph)
{
this->EditingGraph = Graph;
this->CreateEdGraph();
//FGenericCommands::Register();
//FGraphEditorCommands::Register();
//FComboActionGraphEditorCommands::Register();
//if (!this->ToolbarBuilder.IsValid())
//{
// this->ToolbarBuilder = MakeShareable(new FAssetEditorToolbarComboActionGraph(SharedThis(this)));
//}
this->BindCommands();
this->CreateInternalWidgets();
//TSharedPtr<FExtender> ToolbarExtender = MakeShareable(new FExtender);
//this->ToolbarBuilder->AddMounteaDialogueGraphToolbar(ToolbarExtender);
// Layout
//const TSharedRef<FTabManager::FLayout> StandaloneDefaultLayout = FTabManager::NewLayout("Standalone_MounteaDialogueGraphEditor_LayoutV0.3")
// ->AddArea
// (
// FTabManager::NewPrimaryArea()->SetOrientation(Orient_Vertical)
// ->Split
// (
// FTabManager::NewSplitter()->SetOrientation(Orient_Horizontal)->SetSizeCoefficient(0.9f)
// ->Split
// (
// FTabManager::NewStack()
// ->SetSizeCoefficient(3.f)
// ->AddTab(FAssetEditorTabs_MounteaDialogueGraph::ViewportID, ETabState::OpenedTab)->SetHideTabWell(true)
// )
// ->Split
// (
// FTabManager::NewSplitter()->SetOrientation(Orient_Vertical)
// ->Split
// (
// FTabManager::NewSplitter()->SetOrientation(Orient_Vertical)
// ->Split
// (
// FTabManager::NewStack()
// ->SetSizeCoefficient(0.9f)
// ->AddTab(FAssetEditorTabs_MounteaDialogueGraph::MounteaDialogueGraphPropertyID, ETabState::OpenedTab)->SetHideTabWell(true)
// )
// ->Split
// (
// FTabManager::NewStack()
// ->SetSizeCoefficient(0.3f)
// ->AddTab(FAssetEditorTabs_MounteaDialogueGraph::SearchToolbarID, ETabState::OpenedTab)
// )
// )
// )
// )
// );
//const bool bCreateDefaultStandaloneMenu = true;
//const bool bCreateDefaultToolbar = true;
//FAssetEditorToolkit::InitAssetEditor
//(
// Mode,
// InitToolkitHost,
// ComboActionGraphEditorAppName,
// StandaloneDefaultLayout,
// bCreateDefaultStandaloneMenu,
// bCreateDefaultToolbar,
// EditingGraph,
// false
// );
this->RegenerateMenusAndToolbars();
}
UComboActionGraphEditorSettings *FAssetEditor_ComboActionGraph::GetSettings() const
{
return this->ComboActionGraphEditorSettings;
}
void FAssetEditor_ComboActionGraph::RegisterTabSpawners(const TSharedRef<FTabManager> &InTabManager)
{
//WorkspaceMenuCategory = InTabManager->AddLocalWorkspaceMenuCategory(LOCTEXT("WorkspaceMenu_MounteaDialogueTreeEditor", "Mountea Dialogue Tree Editor"));
//auto WorkspaceMenuCategoryRef = WorkspaceMenuCategory.ToSharedRef();
//FAssetEditorToolkit::RegisterTabSpawners(InTabManager);
//InTabManager->RegisterTabSpawner(FAssetEditorTabs_ComboActionGraph::ViewportID, FOnSpawnTab::CreateSP(this, &FAssetEditor_ComboActionGraph::SpawnTab_Viewport))
// .SetDisplayName(LOCTEXT("GraphCanvasTab", "Viewport"))
// .SetGroup(WorkspaceMenuCategoryRef)
// .SetIcon(FSlateIcon(FAppStyle::GetAppStyleSetName(), "GraphEditor.EventGraph_16x"));
//InTabManager->RegisterTabSpawner(FAssetEditorTabs_ComboActionGraph::MounteaDialogueGraphPropertyID, FOnSpawnTab::CreateSP(this, &FAssetEditor_ComboActionGraph::SpawnTab_Details))
// .SetDisplayName(LOCTEXT("DetailsTab", "Property"))
// .SetGroup(WorkspaceMenuCategoryRef)
// .SetIcon(FSlateIcon(FAppStyle::GetAppStyleSetName(), "LevelEditor.Tabs.Details"));
//InTabManager->RegisterTabSpawner(FAssetEditorTabs_ComboActionGraph::SearchToolbarID, FOnSpawnTab::CreateSP(this, &FAssetEditor_ComboActionGraph::SpawnTab_Search))
// .SetDisplayName(LOCTEXT("SearchTab", "Search"))
// .SetGroup(WorkspaceMenuCategoryRef)
// .SetIcon(FSlateIcon(FAppStyle::GetAppStyleSetName(), "Kismet.Tabs.FindResults"));
}
void FAssetEditor_ComboActionGraph::UnregisterTabSpawners(const TSharedRef<FTabManager>& InTabManager)
{
//FAssetEditorToolkit::UnregisterTabSpawners(InTabManager);
//InTabManager->UnregisterTabSpawner(FAssetEditorTabs_ComboActionGraph::ViewportID);
//InTabManager->UnregisterTabSpawner(FAssetEditorTabs_ComboActionGraph::ComboActionGraphPropertyID);
//InTabManager->UnregisterTabSpawner(FAssetEditorTabs_ComboActionGraph::SearchToolbarID);
}
bool FAssetEditor_ComboActionGraph::CloseWindow()
{
const bool bSatisfied = FAssetEditorToolkit::CloseWindow();
if (this->EditingGraph)
{
if (this->EditingGraph->EdGraph)
{
UEdComboActionGraph *EdGraph = Cast<UEdComboActionGraph>(this->EditingGraph->EdGraph);
if (EdGraph->GetComboActionEditorPtr().HasSameObject(this)) EdGraph->ResetDialogueEditorPtr();
}
}
return bSatisfied;
}
FName FAssetEditor_ComboActionGraph::GetToolkitFName() const
{
return FName("FComboActionGraphEditor");
}
FText FAssetEditor_ComboActionGraph::GetBaseToolkitName() const
{
return LOCTEXT("ComboActionGraphEditorAppLabel", "Combo Action Graph Editor");
}
FText FAssetEditor_ComboActionGraph::GetToolkitName() const
{
const bool bDirtyState = this->EditingGraph->GetOutermost()->IsDirty();
FFormatNamedArguments Args;
Args.Add(TEXT("ComboActionGraphName"), FText::FromString(this->EditingGraph->GetName()));
Args.Add(TEXT("DirtyState"), bDirtyState ? FText::FromString(TEXT("*")) : FText::GetEmpty());
return FText::Format(LOCTEXT("ComboActionGraphEditorToolkitName", "{ComboActionGraphName}{DirtyState}"), Args);
}
FText FAssetEditor_ComboActionGraph::GetToolkitToolTipText() const
{
return FAssetEditorToolkit::GetToolTipTextForObject(EditingGraph);
}
FLinearColor FAssetEditor_ComboActionGraph::GetWorldCentricTabColorScale() const
{
return FLinearColor::Gray;
}
FString FAssetEditor_ComboActionGraph::GetWorldCentricTabPrefix() const
{
return TEXT("ComboActionGraphEditor");
}
FString FAssetEditor_ComboActionGraph::GetDocumentationLink() const
{
return TEXT("There should be a link to the documentation here someday.");
}
void FAssetEditor_ComboActionGraph::SaveAsset_Execute()
{
if (this->EditingGraph != nullptr)
{
this->RebuildComboActionGraph();
}
FAssetEditorToolkit::SaveAsset_Execute();
}
void FAssetEditor_ComboActionGraph::UpdateToolbar()
{
// TODO
}
void FAssetEditor_ComboActionGraph::RegisterToolbarTab(const TSharedRef<FTabManager>& InTabManager)
{
FAssetEditorToolkit::RegisterTabSpawners(InTabManager);
}
void FAssetEditor_ComboActionGraph::AddReferencedObjects(FReferenceCollector& Collector)
{
Collector.AddReferencedObject(this->EditingGraph);
Collector.AddReferencedObject(this->EditingGraph->EdGraph);
}
FString FAssetEditor_ComboActionGraph::GetReferencerName() const
{
return TEXT("FAssetEditor_ComboActionGraph");
}
void FAssetEditor_ComboActionGraph::SetDialogueBeingEdited(UComboActionGraph *NewDialogue)
{
if (NewDialogue == nullptr) return;
if (NewDialogue == this->EditingGraph) return;
UComboActionGraph *Previous = this->EditingGraph;
this->EditingGraph = NewDialogue;
this->RemoveEditingObject(Previous);
this->AddEditingObject(NewDialogue);
}
void FAssetEditor_ComboActionGraph::CreateInternalWidgets()
{
this->ViewportWidget = this->CreateViewportWidget();
FDetailsViewArgs Args; //( false, false, true, FDetailsViewArgs::HideNameArea, false );
Args.bUpdatesFromSelection = false;
Args.bLockable = false;
Args.bAllowSearch = true;
Args.NameAreaSettings = FDetailsViewArgs::HideNameArea;
Args.bHideSelectionTip = false;
Args.bShowObjectLabel = false;
FPropertyEditorModule &PropertyModule = FModuleManager::LoadModuleChecked<FPropertyEditorModule>("PropertyEditor");
this->PropertyWidget = PropertyModule.CreateDetailView(Args);
this->PropertyWidget->SetObject(EditingGraph);
this->PropertyWidget->OnFinishedChangingProperties().AddSP(this, &FAssetEditor_ComboActionGraph::OnFinishedChangingProperties);
//this->FindResultsView = SNew(SComboActionSearch, SharedThis(this));
}
TSharedRef<SGraphEditor> FAssetEditor_ComboActionGraph::CreateViewportWidget()
{
const FComboInputEditorModule &Module = FModuleManager::GetModuleChecked<FComboInputEditorModule>("ComboInputEditor");
FGraphAppearanceInfo AppearanceInfo;
AppearanceInfo.CornerText = LOCTEXT("AppearanceCornerText_ComboActionGraph", "Combo Action Tree");
AppearanceInfo.CornerImage = Module.Get().ComboActionGraphEditorStyleSet->GetBrush(TEXT("MDSStyleSet.Graph.CornerImage"));
AppearanceInfo.InstructionText = LOCTEXT("InstructionText_ComboActionGraph", "Place action nodes by right clicking.");
this->CreateCommandList();
SGraphEditor::FGraphEditorEvents InEvents;
InEvents.OnSelectionChanged = SGraphEditor::FOnSelectionChanged::CreateSP(this, &FAssetEditor_ComboActionGraph::OnSelectedNodesChanged);
InEvents.OnNodeDoubleClicked = FSingleNodeEvent::CreateSP(this, &FAssetEditor_ComboActionGraph::OnNodeDoubleClicked);
return SNew(SGraphEditor)
.AdditionalCommands(GraphEditorCommands)
.IsEditable(true)
.Appearance(AppearanceInfo)
.GraphToEdit(EditingGraph->EdGraph)
.GraphEvents(InEvents)
.AutoExpandActionMenu(true)
.ShowGraphStateOverlay(false);
}
void FAssetEditor_ComboActionGraph::BindCommands()
{
//this->ToolkitCommands->MapAction
//(
// FComboActionGraphEditorCommands::Get().AutoArrange,
// FExecuteAction::CreateSP(this, &FAssetEditor_ComboActionGraph::AutoArrange),
// FCanExecuteAction::CreateSP(this, &FAssetEditor_ComboActionGraph::CanAutoArrange)
//);
//this->ToolkitCommands->MapAction
//(
// FComboActionGraphEditorCommands::Get().ValidateGraph,
// FExecuteAction::CreateSP(this, &FAssetEditor_ComboActionGraph::ValidateGraph),
// FCanExecuteAction::CreateSP(this, &FAssetEditor_ComboActionGraph::CanValidateGraph)
//);
//
//this->ToolkitCommands->MapAction
//(
// FComboActionGraphEditorCommands::Get().FindInDialogue,
// FExecuteAction::CreateLambda([this] { this->SummonSearchUI(); })
//);
}
void FAssetEditor_ComboActionGraph::CreateEdGraph()
{
if (this->EditingGraph->EdGraph == nullptr)
{
this->EditingGraph->EdGraph = CastChecked<UEdComboActionGraph>(FBlueprintEditorUtils::CreateNewGraph(EditingGraph, NAME_None, UEdComboActionGraph::StaticClass(), UComboActionGraphSchema::StaticClass()));
this->EditingGraph->EdGraph->bAllowDeletion = false;
// Give the schema a chance to fill out any required nodes (like the results node)
const UEdGraphSchema *Schema = this->EditingGraph->EdGraph->GetSchema();
Schema->CreateDefaultNodesForGraph(*this->EditingGraph->EdGraph);
UEdComboActionGraph *ComboActionGraph = Cast<UEdComboActionGraph>(this->EditingGraph->EdGraph);
UEdComboActionGraphNode *NewNode = ComboActionGraph->CreateIntermediateNode<UEdComboActionGraphNode>();
NewNode->SetComboActionGraphNode(this->EditingGraph->StartNode);
NewNode->CreateNewGuid();
NewNode->PostPlacedNewNode();
NewNode->AllocateDefaultPins();
NewNode->AutowireNewNode(nullptr);
NewNode->NodePosX = 0;
NewNode->NodePosY = 0;
NewNode->ComboActionGraphNode->SetFlags(EObjectFlags::RF_Transactional);
NewNode->SetFlags(EObjectFlags::RF_Transactional);
ComboActionGraph->RebuildComboActionGraph();
}
if (UEdComboActionGraph *EdComboActionGraph = Cast<UEdComboActionGraph>(this->EditingGraph->EdGraph))
{
EdComboActionGraph->SetDialogueEditorPtr(SharedThis(this));
EdComboActionGraph->RebuildComboActionGraph();
}
}
void FAssetEditor_ComboActionGraph::CreateCommandList()
{
if (this->GraphEditorCommands.IsValid())
{
return;
}
this->GraphEditorCommands = MakeShareable(new FUICommandList);
//this->GraphEditorCommands->MapAction(FComboActionGraphEditorCommands::Get().AutoArrange,
// FExecuteAction::CreateRaw(this, &FAssetEditor_ComboActionGraph::AutoArrange),
// FCanExecuteAction::CreateRaw(this, &FAssetEditor_ComboActionGraph::CanAutoArrange));
//this->GraphEditorCommands->MapAction(FComboActionGraphEditorCommands::Get().ValidateGraph,
// FExecuteAction::CreateRaw(this, &FAssetEditor_ComboActionGraph::ValidateGraph),
// FCanExecuteAction::CreateRaw(this, &FAssetEditor_ComboActionGraph::CanValidateGraph));
this->GraphEditorCommands->MapAction(FGenericCommands::Get().SelectAll,
FExecuteAction::CreateRaw(this, &FAssetEditor_ComboActionGraph::SelectAllNodes),
FCanExecuteAction::CreateRaw(this, &FAssetEditor_ComboActionGraph::CanSelectAllNodes)
);
this->GraphEditorCommands->MapAction(FGenericCommands::Get().Delete,
FExecuteAction::CreateRaw(this, &FAssetEditor_ComboActionGraph::DeleteSelectedNodes),
FCanExecuteAction::CreateRaw(this, &FAssetEditor_ComboActionGraph::CanDeleteNodes)
);
this->GraphEditorCommands->MapAction(FGenericCommands::Get().Copy,
FExecuteAction::CreateRaw(this, &FAssetEditor_ComboActionGraph::CopySelectedNodes),
FCanExecuteAction::CreateRaw(this, &FAssetEditor_ComboActionGraph::CanCopyNodes)
);
this->GraphEditorCommands->MapAction(FGenericCommands::Get().Cut,
FExecuteAction::CreateRaw(this, &FAssetEditor_ComboActionGraph::CutSelectedNodes),
FCanExecuteAction::CreateRaw(this, &FAssetEditor_ComboActionGraph::CanCutNodes)
);
this->GraphEditorCommands->MapAction(FGenericCommands::Get().Paste,
FExecuteAction::CreateRaw(this, &FAssetEditor_ComboActionGraph::PasteNodes),
FCanExecuteAction::CreateRaw(this, &FAssetEditor_ComboActionGraph::CanPasteNodes)
);
this->GraphEditorCommands->MapAction(FGenericCommands::Get().Duplicate,
FExecuteAction::CreateRaw(this, &FAssetEditor_ComboActionGraph::DuplicateNodes),
FCanExecuteAction::CreateRaw(this, &FAssetEditor_ComboActionGraph::CanDuplicateNodes)
);
this->GraphEditorCommands->MapAction(FGenericCommands::Get().Rename,
FExecuteAction::CreateSP(this, &FAssetEditor_ComboActionGraph::OnRenameNode),
FCanExecuteAction::CreateSP(this, &FAssetEditor_ComboActionGraph::CanRenameNodes)
);
//this->ToolkitCommands->MapAction
//(
// FComboActionGraphEditorCommands::Get().FindInDialogue,
// FExecuteAction::CreateLambda([this] { SummonSearchUI(); })
//);
}
TSharedPtr<SGraphEditor> FAssetEditor_ComboActionGraph::GetCurrentGraphEditor() const
{
return this->ViewportWidget;
}
FGraphPanelSelectionSet FAssetEditor_ComboActionGraph::GetSelectedNodes() const
{
FGraphPanelSelectionSet CurrentSelection;
TSharedPtr<SGraphEditor> FocusedGraphEd = this->GetCurrentGraphEditor();
if (FocusedGraphEd.IsValid())
{
CurrentSelection = FocusedGraphEd->GetSelectedNodes();
}
return CurrentSelection;
}
void FAssetEditor_ComboActionGraph::RebuildComboActionGraph()
{
if (this->EditingGraph == nullptr)
{
UE_LOG(LogAssetEditorComboActionGraph, Warning, TEXT("[RebuildComboActionGraph] EditingGraph is nullptr"));
return;
}
UEdComboActionGraph *EdGraph = Cast<UEdComboActionGraph>(this->EditingGraph->EdGraph);
check(EdGraph != nullptr);
EdGraph->RebuildComboActionGraph();
}
void FAssetEditor_ComboActionGraph::SummonSearchUI(FString NewSearch, bool bSelectFirstResult)
{
//TSharedPtr<SMounteaDialogueSearch> FindResultsToUse;
//FindResultsToUse = FindResultsView;
//FMounteaDialogueSearchHelpers::InvokeTab(TabManager, FAssetEditorTabs_MounteaDialogueGraph::SearchToolbarID);
//if (FindResultsToUse.IsValid())
//{
// FMounteaDialogueSearchFilter Filter;
// Filter.SearchString = NewSearch;
// FindResultsToUse->FocusForUse(Filter, bSelectFirstResult);
//}
}
void FAssetEditor_ComboActionGraph::SelectAllNodes()
{
TSharedPtr<SGraphEditor> CurrentGraphEditor = this->GetCurrentGraphEditor();
if (CurrentGraphEditor.IsValid())
{
CurrentGraphEditor->SelectAllNodes();
}
}
bool FAssetEditor_ComboActionGraph::CanSelectAllNodes()
{
return true;
}
void FAssetEditor_ComboActionGraph::DeleteSelectedNodes()
{
TSharedPtr<SGraphEditor> CurrentGraphEditor = this->GetCurrentGraphEditor();
if (!CurrentGraphEditor.IsValid())
{
return;
}
const FScopedTransaction Transaction(FGenericCommands::Get().Delete->GetDescription());
CurrentGraphEditor->GetCurrentGraph()->Modify();
const FGraphPanelSelectionSet SelectedNodes = CurrentGraphEditor->GetSelectedNodes();
CurrentGraphEditor->ClearSelectionSet();
for (FGraphPanelSelectionSet::TConstIterator NodeIt(SelectedNodes); NodeIt; ++NodeIt)
{
UEdGraphNode* EdNode = Cast<UEdGraphNode>(*NodeIt);
if (EdNode == nullptr || !EdNode->CanUserDeleteNode())
continue;;
if (UEdComboActionGraphNode *EdNode_Node = Cast<UEdComboActionGraphNode>(EdNode))
{
EdNode_Node->Modify();
const UEdGraphSchema *Schema = EdNode_Node->GetSchema();
if (Schema != nullptr)
{
Schema->BreakNodeLinks(*EdNode_Node);
}
EdNode_Node->DestroyNode();
}
else
{
EdNode->Modify();
EdNode->DestroyNode();
}
}
// Update UI
CurrentGraphEditor->NotifyGraphChanged();
UEdGraph *EdGraph = CurrentGraphEditor->GetCurrentGraph();
UObject *GraphOwner = EdGraph->GetOuter();
if (GraphOwner)
{
GraphOwner->PostEditChange();
GraphOwner->MarkPackageDirty();
}
this->RebuildComboActionGraph();
}
bool FAssetEditor_ComboActionGraph::CanDeleteNodes()
{
// If any of the nodes can be deleted then we should allow deleting
const FGraphPanelSelectionSet SelectedNodes = this->GetSelectedNodes();
for (FGraphPanelSelectionSet::TConstIterator SelectedIter(SelectedNodes); SelectedIter; ++SelectedIter)
{
UEdGraphNode* Node = Cast<UEdGraphNode>(*SelectedIter);
if (Node != nullptr && Node->CanUserDeleteNode())
{
return true;
}
}
return false;
}
void FAssetEditor_ComboActionGraph::DeleteSelectedDuplicatableNodes()
{
TSharedPtr<SGraphEditor> CurrentGraphEditor = this->GetCurrentGraphEditor();
if (!CurrentGraphEditor.IsValid())
{
return;
}
const FGraphPanelSelectionSet OldSelectedNodes = CurrentGraphEditor->GetSelectedNodes();
CurrentGraphEditor->ClearSelectionSet();
for (FGraphPanelSelectionSet::TConstIterator SelectedIter(OldSelectedNodes); SelectedIter; ++SelectedIter)
{
UEdGraphNode *Node = Cast<UEdGraphNode>(*SelectedIter);
if (Node && Node->CanDuplicateNode())
{
CurrentGraphEditor->SetNodeSelection(Node, true);
}
}
// Delete the duplicatable nodes
this->DeleteSelectedNodes();
CurrentGraphEditor->ClearSelectionSet();
for (FGraphPanelSelectionSet::TConstIterator SelectedIter(OldSelectedNodes); SelectedIter; ++SelectedIter)
{
if (UEdGraphNode* Node = Cast<UEdGraphNode>(*SelectedIter))
{
CurrentGraphEditor->SetNodeSelection(Node, true);
}
}
}
void FAssetEditor_ComboActionGraph::CutSelectedNodes()
{
this->CopySelectedNodes();
this->DeleteSelectedDuplicatableNodes();
}
bool FAssetEditor_ComboActionGraph::CanCutNodes()
{
return this->CanCopyNodes() && this->CanDeleteNodes();
}
void FAssetEditor_ComboActionGraph::CopySelectedNodes()
{
// Export the selected nodes and place the text on the clipboard
FGraphPanelSelectionSet SelectedNodes = this->GetSelectedNodes();
FString ExportedText;
for (FGraphPanelSelectionSet::TIterator SelectedIter(SelectedNodes); SelectedIter; ++SelectedIter)
{
UEdGraphNode* Node = Cast<UEdGraphNode>(*SelectedIter);
if (Node == nullptr)
{
SelectedIter.RemoveCurrent();
continue;
}
if (UEdComboActionGraphEdge *EdNode_Edge = Cast<UEdComboActionGraphEdge>(*SelectedIter))
{
UEdComboActionGraphNode *StartNode = EdNode_Edge->GetStartNode();
UEdComboActionGraphNode *EndNode = EdNode_Edge->GetEndNode();
if (!SelectedNodes.Contains(StartNode) || !SelectedNodes.Contains(EndNode))
{
SelectedIter.RemoveCurrent();
continue;
}
}
Node->PrepareForCopying();
}
FEdGraphUtilities::ExportNodesToText(SelectedNodes, ExportedText);
FPlatformApplicationMisc::ClipboardCopy(*ExportedText);
}
bool FAssetEditor_ComboActionGraph::CanCopyNodes()
{
// If any of the nodes can be duplicated then we should allow copying
const FGraphPanelSelectionSet SelectedNodes = this->GetSelectedNodes();
for (FGraphPanelSelectionSet::TConstIterator SelectedIter(SelectedNodes); SelectedIter; ++SelectedIter)
{
UEdGraphNode *Node = Cast<UEdGraphNode>(*SelectedIter);
if (Node && Node->CanDuplicateNode() == false)
{
return false;
}
}
return true;
}
void FAssetEditor_ComboActionGraph::PasteNodes()
{
TSharedPtr<SGraphEditor> CurrentGraphEditor = this->GetCurrentGraphEditor();
if (CurrentGraphEditor.IsValid())
{
PasteNodesHere(CurrentGraphEditor->GetPasteLocation());
}
}
void FAssetEditor_ComboActionGraph::PasteNodesHere(const FVector2D& Location)
{
// Find the graph editor with focus
TSharedPtr<SGraphEditor> CurrentGraphEditor = this->GetCurrentGraphEditor();
if (!CurrentGraphEditor.IsValid())
{
return;
}
// Select the newly pasted stuff
UEdGraph* EdGraph = CurrentGraphEditor->GetCurrentGraph();
{
const FScopedTransaction Transaction(FGenericCommands::Get().Paste->GetDescription());
EdGraph->Modify();
// Clear the selection set (newly pasted stuff will be selected)
CurrentGraphEditor->ClearSelectionSet();
// Grab the text to paste from the clipboard.
FString TextToImport;
FPlatformApplicationMisc::ClipboardPaste(TextToImport);
// Import the nodes
TSet<UEdGraphNode*> PastedNodes;
FEdGraphUtilities::ImportNodesFromText(EdGraph, TextToImport, PastedNodes);
//Average position of nodes so we can move them while still maintaining relative distances to each other
FVector2D AvgNodePosition(0.0f, 0.0f);
for (TSet<UEdGraphNode*>::TIterator It(PastedNodes); It; ++It)
{
UEdGraphNode* Node = *It;
AvgNodePosition.X += Node->NodePosX;
AvgNodePosition.Y += Node->NodePosY;
}
float InvNumNodes = 1.0f / float(PastedNodes.Num());
AvgNodePosition.X *= InvNumNodes;
AvgNodePosition.Y *= InvNumNodes;
// 0 is always Start Node!
int32 SharedIndex = EditingGraph->GetAllNodes().Num();
for (TSet<UEdGraphNode*>::TIterator It(PastedNodes); It; ++It)
{
UEdGraphNode* Node = *It;
CurrentGraphEditor->SetNodeSelection(Node, true);
Node->NodePosX = (Node->NodePosX - AvgNodePosition.X) + Location.X;
Node->NodePosY = (Node->NodePosY - AvgNodePosition.Y) + Location.Y;
Node->SnapToGrid(16);
// Give new node a different Guid from the old one
Node->CreateNewGuid();
if (UEdComboActionGraphNode *MounteaNode = Cast<UEdComboActionGraphNode>(Node))
{
if (MounteaNode->ComboActionGraphNode)
{
MounteaNode->ComboActionGraphNode->OnPasted();
//MounteaNode->SetDialogueNodeIndex(SharedIndex);
}
SharedIndex++;
}
}
}
// Update UI
CurrentGraphEditor->NotifyGraphChanged();
UObject* GraphOwner = EdGraph->GetOuter();
if (GraphOwner)
{
GraphOwner->PostEditChange();
GraphOwner->MarkPackageDirty();
}
this->RebuildComboActionGraph();
}
bool FAssetEditor_ComboActionGraph::CanPasteNodes()
{
const FGraphPanelSelectionSet SelectedNodes = this->GetSelectedNodes();
for (FGraphPanelSelectionSet::TConstIterator SelectedIter(SelectedNodes); SelectedIter; ++SelectedIter)
{
const UEdComboActionGraphNode *Node = Cast<UEdComboActionGraphNode>(*SelectedIter);
if (Node && Node->CanUserPasteNodes() == false)
{
return false;
}
}
TSharedPtr<SGraphEditor> CurrentGraphEditor = this->GetCurrentGraphEditor();
if (!CurrentGraphEditor.IsValid())
{
return false;
}
FString ClipboardContent;
FPlatformApplicationMisc::ClipboardPaste(ClipboardContent);
return FEdGraphUtilities::CanImportNodesFromText(CurrentGraphEditor->GetCurrentGraph(), ClipboardContent);
}
void FAssetEditor_ComboActionGraph::DuplicateNodes()
{
this->CopySelectedNodes();
this->PasteNodes();
}
bool FAssetEditor_ComboActionGraph::CanDuplicateNodes()
{
return this->CanCopyNodes();
}
void FAssetEditor_ComboActionGraph::AutoArrange()
{
UEdComboActionGraph *EdGraph = Cast<UEdComboActionGraph>(this->EditingGraph->EdGraph);
check(EdGraph != nullptr);
const FScopedTransaction Transaction(LOCTEXT("ComboActionGraphEditorAutoArrange", "Combo Action Graph Editor: Auto Arrange all Nodes"));
EdGraph->Modify(true);
//UComboActionGraphLayoutStrategy *LayoutStrategy = nullptr;
//switch (this->ComboActionGraphEditorSettings->GetAutoLayoutStrategy())
//{
// case EComboActionAutoLayoutStrategyType::Tree:
// LayoutStrategy = NewObject<UComboActionGraphLayoutStrategy>(EdGraph, UTreeSolveLayoutStrategy::StaticClass());
// break;
// case EComboActionAutoLayoutStrategyType::ForceDirected:
// LayoutStrategy = NewObject<UComboActionGraphLayoutStrategy>(EdGraph, UForceDirectedSolveLayoutStrategy::StaticClass());
// break;
// default:
// break;
//}
//if (LayoutStrategy != nullptr)
//{
// LayoutStrategy->Layout(EdGraph);
// LayoutStrategy->ConditionalBeginDestroy();
//}
//else
//{
// LOG_ERROR(TEXT("[AutoArrange] LayoutStrategy is null."));
//}
}
bool FAssetEditor_ComboActionGraph::CanAutoArrange() const
{
return this->EditingGraph != nullptr && Cast<UEdComboActionGraph>(this->EditingGraph->EdGraph) != nullptr;
}
void FAssetEditor_ComboActionGraph::ValidateGraph()
{
if (this->ValidationWindow.IsValid())
{
this->ValidationWindow->RequestDestroyWindow();
}
UEdComboActionGraph *EdGraph = Cast<UEdComboActionGraph>(this->EditingGraph->EdGraph);
check(EdGraph != nullptr);
const FScopedTransaction Transaction(LOCTEXT("ComboActionGraphEditorValidateGraph", "Combo Action Graph Editor: Validate Graph."));
UComboActionGraph *ComboActionGraph = EdGraph->GetComboActionGraph();
check(ComboActionGraph != nullptr);
this->RebuildComboActionGraph();
//TArray<FText> ValidationMessages;
//if (ComboActionGraph->ValidateGraph(ValidationMessages, true) == false)
//{
// ValidationWindow = MDSPopup_GraphValidation::Open(ValidationMessages);
//}
//else
//{
// ValidationMessages.Empty();
// ValidationWindow = MDSPopup_GraphValidation::Open(ValidationMessages);
//}
}
bool FAssetEditor_ComboActionGraph::CanValidateGraph() const
{
return true;
}
void FAssetEditor_ComboActionGraph::OnRenameNode()
{
TSharedPtr<SGraphEditor> CurrentGraphEditor = this->GetCurrentGraphEditor();
if (CurrentGraphEditor.IsValid())
{
const FGraphPanelSelectionSet SelectedNodes = GetSelectedNodes();
for (FGraphPanelSelectionSet::TConstIterator NodeIt(SelectedNodes); NodeIt; ++NodeIt)
{
UEdGraphNode *SelectedNode = Cast<UEdGraphNode>(*NodeIt);
if (SelectedNode != nullptr && SelectedNode->bCanRenameNode)
{
CurrentGraphEditor->IsNodeTitleVisible(SelectedNode, true);
break;
}
}
}
}
bool FAssetEditor_ComboActionGraph::CanRenameNodes() const
{
check(this->GetSettings() != nullptr);
return this->GetSettings()->AllowRenameNodes() == true && this->GetSelectedNodes().Num() == 1;
}
void FAssetEditor_ComboActionGraph::OnSelectedNodesChanged(const TSet<UObject*> &NewSelection)
{
TArray<UObject*> Selection;
for (UObject* SelectionEntry : NewSelection)
{
Selection.Add(SelectionEntry);
}
if (Selection.Num() == 1)
{
// When just one node is selected, add it to PropertyWidget
this->PropertyWidget->SetObjects(Selection);
this->PropertyWidget->ShowAllAdvancedProperties();
//UComboActionEditorBFC::TriggerPreviewRefresh(Selection);
}
else
{
this->PropertyWidget->SetObject(this->EditingGraph);
}
this->RebuildComboActionGraph();
}
void FAssetEditor_ComboActionGraph::OnNodeDoubleClicked(UEdGraphNode *Node)
{
this->GraphEditorCommands->TryExecuteAction(FGenericCommands::Get().Rename.ToSharedRef());
}
void FAssetEditor_ComboActionGraph::OnFinishedChangingProperties(const FPropertyChangedEvent& PropertyChangedEvent)
{
if (this->EditingGraph == nullptr)
return;
this->EditingGraph->EdGraph->GetSchema()->ForceVisualizationCacheClear();
this->RebuildComboActionGraph();
}
TSharedRef<SDockTab> FAssetEditor_ComboActionGraph::SpawnTab_Viewport(const FSpawnTabArgs &Args)
{
//check(Args.GetTabId() == FAssetEditorTabs_ComboActionGraph::ViewportID);
TSharedRef<SDockTab> SpawnedTab = SNew(SDockTab)
.Label(LOCTEXT("ViewportTab_Title", "Viewport"));
if (this->ViewportWidget.IsValid())
{
SpawnedTab->SetContent(this->ViewportWidget.ToSharedRef());
}
return SpawnedTab;
}
TSharedRef<SDockTab> FAssetEditor_ComboActionGraph::SpawnTab_Details(const FSpawnTabArgs& Args)
{
//check(Args.GetTabId() == FAssetEditorTabs_ComboActionGraph::ComboActionGraphPropertyID);
auto DockTab = SNew(SDockTab)
.Label(LOCTEXT("Details_Title", "Property"))
[
PropertyWidget.ToSharedRef()
];
DockTab->SetTabIcon(FAppStyle::GetBrush("LevelEditor.Tabs.Details"));
return DockTab;
}
TSharedRef<SDockTab> FAssetEditor_ComboActionGraph::SpawnTab_Search(const FSpawnTabArgs& Args)
{
//check(Args.GetTabId() == FAssetEditorTabs_MounteaDialogueGraph::SearchToolbarID);
//auto DockTab = SNew(SDockTab)
// .Label(LOCTEXT("Search_Title", "Search"))
// [
// this->FindResultsView.ToSharedRef()
// ];
//DockTab->SetTabIcon(FAppStyle::GetBrush("Kismet.Tabs.FindResults"));
//return DockTab;
return SNew(SDockTab);
}
#undef LOCTEXT_NAMESPACE

View File

@ -0,0 +1,167 @@
// Copyright Dominik Pavlicek 2023. All Rights Reserved.
#pragma once
//#include "Search/SComboActionSearch.h"
DECLARE_LOG_CATEGORY_EXTERN(LogAssetEditorComboActionGraph, Log, All);
class COMBOINPUTEDITOR_API FAssetEditor_ComboActionGraph : public FAssetEditorToolkit, public FNotifyHook, public FGCObject
{
public:
FAssetEditor_ComboActionGraph();
virtual ~FAssetEditor_ComboActionGraph() override;
void OnPackageSaved(const FString &String, UPackage *Package, FObjectPostSaveContext ObjectPostSaveContext);
void InitComboActionGraphAssetEditor(const EToolkitMode::Type Mode, const TSharedPtr<IToolkitHost> &InitToolkitHost, class UComboActionGraph *Graph);
class UComboActionGraphEditorSettings *GetSettings() const;
#pragma region ToolkitInterface
public:
// IToolkit interface
virtual void RegisterTabSpawners(const TSharedRef<FTabManager> &InTabManager) override;
virtual void UnregisterTabSpawners(const TSharedRef<FTabManager> &InTabManager) override;
virtual bool CloseWindow() override;
// End of IToolkit interface
#pragma endregion
#pragma region AssetEditorToolkit
virtual FName GetToolkitFName() const override;
virtual FText GetBaseToolkitName() const override;
virtual FText GetToolkitName() const override;
virtual FText GetToolkitToolTipText() const override;
virtual FLinearColor GetWorldCentricTabColorScale() const override;
virtual FString GetWorldCentricTabPrefix() const override;
virtual FString GetDocumentationLink() const override;
virtual void SaveAsset_Execute() override;
#pragma endregion
#pragma region Toolbar
void UpdateToolbar();
//TSharedPtr<FAssetEditorToolbarComboActionGraph> GetToolbarBuilder() { return ToolbarBuilder; }
void RegisterToolbarTab(const TSharedRef<class FTabManager> &InTabManager);
#pragma endregion
#pragma region SerializableObjectInterface
virtual void AddReferencedObjects(FReferenceCollector &Collector) override;
#pragma endregion
#pragma region FGCObject
virtual FString GetReferencerName() const override;
#pragma endregion
// Gets/Sets the dialogue being edited
class UComboActionGraph *GetEditingGraphSafe()
{
check(EditingGraph);
return EditingGraph;
}
void SetDialogueBeingEdited(class UComboActionGraph *NewDialogue);
virtual void JumpToNode(const class UEdGraphNode *JumpToMe, bool bRequestRename = false, bool bSelectNode = true)
{
if (this->ViewportWidget.IsValid())
{
this->ViewportWidget->JumpToNode(JumpToMe, bRequestRename, bSelectNode);
}
}
private:
void CreateInternalWidgets();
TSharedRef<SGraphEditor> CreateViewportWidget();
void BindCommands();
void CreateEdGraph();
void CreateCommandList();
TSharedPtr<SGraphEditor> GetCurrentGraphEditor() const;
FGraphPanelSelectionSet GetSelectedNodes() const;
void RebuildComboActionGraph();
void SummonSearchUI(FString NewSearch = FString(), bool bSelectFirstResult = false);
#pragma region GraphEditorCommands
void SelectAllNodes();
bool CanSelectAllNodes();
void DeleteSelectedNodes();
bool CanDeleteNodes();
void DeleteSelectedDuplicatableNodes();
void CutSelectedNodes();
bool CanCutNodes();
void CopySelectedNodes();
bool CanCopyNodes();
void PasteNodes();
void PasteNodesHere(const FVector2D &Location);
bool CanPasteNodes();
void DuplicateNodes();
bool CanDuplicateNodes();
void AutoArrange();
bool CanAutoArrange() const;
void ValidateGraph();
bool CanValidateGraph() const;
void OnRenameNode();
bool CanRenameNodes() const;
#pragma endregion
#pragma region GraphEditorEvents
void OnSelectedNodesChanged(const TSet<class UObject*> &NewSelection);
void OnNodeDoubleClicked(UEdGraphNode *Node);
void OnFinishedChangingProperties(const FPropertyChangedEvent &PropertyChangedEvent);
//void OnPackageSaved(const FString &PackageFileName, UObject *Outer);
#pragma endregion
#pragma region Variables
private:
TSharedRef<SDockTab> SpawnTab_Viewport(const FSpawnTabArgs &Args);
TSharedRef<SDockTab> SpawnTab_Details(const FSpawnTabArgs &Args);
TSharedRef<SDockTab> SpawnTab_Search(const FSpawnTabArgs &Args);
class UComboActionGraphEditorSettings *ComboActionGraphEditorSettings;
class UComboActionGraph *EditingGraph;
//Toolbar
//TSharedPtr<FAssetEditorToolbarComboActionGraph> ToolbarBuilder;
/** Handle to the registered OnPackageSave delegate */
FDelegateHandle OnPackageSavedDelegateHandle;
TSharedPtr<SGraphEditor> ViewportWidget;
TSharedPtr<class IDetailsView> PropertyWidget;
//TSharedPtr<SComboActionSearch> FindResultsView;
/** The command list for this editor */
TSharedPtr<FUICommandList> GraphEditorCommands;
TSharedPtr<SWindow> ValidationWindow;
#pragma endregion
};

View File

@ -3,6 +3,7 @@
#include "Ed/EdComboActionGraph.h"
#include "ComboActionGraph.h"
#include "Ed/AssetEditor_ComboActionGraph.h"
#include "Ed/EdComboActionGraphEdge.h"
#include "Ed/EdComboActionGraphNode.h"
#include "Nodes/ComboActionGraphEdge.h"
@ -20,18 +21,18 @@ void UEdComboActionGraph::RebuildComboActionGraph()
UComboActionGraph *Graph = GetComboActionGraph();
Clear();
this->Clear();
for (int i = 0; i < Nodes.Num(); ++i)
for (const TObjectPtr<UEdGraphNode> &Node : this->Nodes)
{
if (UEdComboActionGraphNode *EdNode = Cast<UEdComboActionGraphNode>(Nodes[i]))
if (UEdComboActionGraphNode *EdNode = Cast<UEdComboActionGraphNode>(Node))
{
if (EdNode->ComboActionGraphNode == nullptr)
continue;
UComboActionGraphNode *ComboActionGraphNode = EdNode->ComboActionGraphNode;
NodeMap.Add(ComboActionGraphNode, EdNode);
this->NodeMap.Add(ComboActionGraphNode, EdNode);
Graph->AllNodes.Add(ComboActionGraphNode);
@ -73,7 +74,7 @@ void UEdComboActionGraph::RebuildComboActionGraph()
}
}
}
else if (UEdComboActionGraphEdge *EdgeNode = Cast<UEdComboActionGraphEdge>(Nodes[i]))
else if (UEdComboActionGraphEdge *EdgeNode = Cast<UEdComboActionGraphEdge>(Node))
{
UEdComboActionGraphNode *StartNode = EdgeNode->GetStartNode();
UEdComboActionGraphNode *EndNode = EdgeNode->GetEndNode();
@ -81,11 +82,11 @@ void UEdComboActionGraph::RebuildComboActionGraph()
if (StartNode == nullptr || EndNode == nullptr || Edge == nullptr)
{
UE_LOG(LogEdComboActionGraph, Error, TEXT("[RebuildMounteaDialogueGraph] Add edge failed."));
UE_LOG(LogEdComboActionGraph, Error, TEXT("[RebuildComboActionGraph] Add edge failed."));
continue;
}
EdgeMap.Add(Edge, EdgeNode);
this->EdgeMap.Add(Edge, EdgeNode);
Edge->Graph = Graph;
Edge->Rename(nullptr, Graph, REN_DontCreateRedirectors | REN_DoNotDirty);
@ -95,9 +96,8 @@ void UEdComboActionGraph::RebuildComboActionGraph()
}
}
for (int i = 0; i < Graph->AllNodes.Num(); ++i)
for (UComboActionGraphNode *Node : Graph->AllNodes)
{
UComboActionGraphNode *Node = Graph->AllNodes[i];
if (Node->ParentNodes.Num() == 0)
{
Graph->RootNodes.Add(Node);
@ -111,8 +111,8 @@ void UEdComboActionGraph::RebuildComboActionGraph()
Graph->RootNodes.Sort([&](const UComboActionGraphNode &L, const UComboActionGraphNode &R)
{
UEdComboActionGraphNode* EdNode_LNode = NodeMap[&L];
UEdComboActionGraphNode* EdNode_RNode = NodeMap[&R];
UEdComboActionGraphNode *EdNode_LNode = this->NodeMap[&L];
UEdComboActionGraphNode *EdNode_RNode = this->NodeMap[&R];
return EdNode_LNode->NodePosX < EdNode_RNode->NodePosX;
});
}
@ -128,9 +128,9 @@ bool UEdComboActionGraph::Modify(bool bAlwaysMarkDirty)
this->GetComboActionGraph()->Modify();
for (int32 i = 0; i < Nodes.Num(); ++i)
for (TObjectPtr<UEdGraphNode> &Node : this->Nodes)
{
Nodes[i]->Modify();
Node->Modify();
}
return Rtn;
@ -138,20 +138,21 @@ bool UEdComboActionGraph::Modify(bool bAlwaysMarkDirty)
void UEdComboActionGraph::PostEditUndo()
{
NotifyGraphChanged();
this->NotifyGraphChanged();
Super::PostEditUndo();
}
//void UEdComboActionGraph::SetDialogueEditorPtr(TWeakPtr<FAssetEditor_MounteaDialogueGraph> NewPtr)
//{
// DialogueEditorPtr = NewPtr;
//}
void UEdComboActionGraph::SetDialogueEditorPtr(TWeakPtr<FAssetEditor_ComboActionGraph> NewPtr)
{
this->ComboActionEditorPtr = NewPtr;
}
//bool UEdComboActionGraph::JumpToNode(const UMounteaDialogueGraphNode* Node)
//{
// return FComboActionGraphEditorUtilities::OpenEditorAndJumpToGraphNode(DialogueEditorPtr, *NodeMap.Find(Node));
//}
bool UEdComboActionGraph::JumpToNode(const UComboActionGraphNode *Node)
{
//return FComboActionGraphEditorUtilities::OpenEditorAndJumpToGraphNode(this->ComboActionEditorPtr, *NodeMap.Find(Node));
return false;
}
void UEdComboActionGraph::Clear()
{

View File

@ -23,14 +23,13 @@ public:
virtual bool Modify(bool bAlwaysMarkDirty) override;
virtual void PostEditUndo() override;
//TWeakPtr<FAssetEditor_ComboActionGraph> GetDialogueEditorPtr() const { return DialogueEditorPtr; }
//void SetDialogueEditorPtr(TWeakPtr<FAssetEditor_ComboActionGraph> NewPtr);
//void ResetDialogueEditorPtr() { DialogueEditorPtr.Reset(); }
TWeakPtr<class FAssetEditor_ComboActionGraph> GetComboActionEditorPtr() const { return this->ComboActionEditorPtr; }
void SetDialogueEditorPtr(TWeakPtr<class FAssetEditor_ComboActionGraph> NewPtr);
void ResetDialogueEditorPtr() { this->ComboActionEditorPtr.Reset(); }
//bool JumpToNode(const class UComboActionGraphNode *Node);
bool JumpToNode(const class UComboActionGraphNode *Node);
public:
UPROPERTY(Transient)
TMap<class UComboActionGraphNode*, class UEdComboActionGraphNode*> NodeMap;
@ -38,12 +37,10 @@ public:
TMap<class UComboActionGraphEdge*, class UEdComboActionGraphEdge*> EdgeMap;
protected:
void Clear();
void SortNodes(UComboActionGraphNode *RootNode);
private:
/** Pointer back to the Dialogue editor that owns us */
//TWeakPtr<FAssetEditor_ComboActionGraph> DialogueEditorPtr;
/** Pointer back to the combo action editor that owns us */
TWeakPtr<FAssetEditor_ComboActionGraph> ComboActionEditorPtr;
};

View File

@ -23,6 +23,19 @@ UEdComboActionGraphNode::UEdComboActionGraphNode()
bAllowPaste = true;
}
void UEdComboActionGraphNode::SetComboActionGraphNode(UComboActionGraphNode *NewNode)
{
this->ComboActionGraphNode = NewNode;
if (this->ComboActionGraphNode)
{
this->bAllowCopy = this->ComboActionGraphNode->bAllowCopy;
this->bAllowDelete = this->ComboActionGraphNode->bAllowDelete;
this->bAllowDuplicate = this->ComboActionGraphNode->bAllowPaste;
this->bAllowPaste = this->ComboActionGraphNode->bAllowPaste;
}
}
UEdComboActionGraph *UEdComboActionGraphNode::GetEdComboActionGraph() const
{
return Cast<UEdComboActionGraph>(this->GetGraph());

View File

@ -23,6 +23,7 @@ class UEdComboActionGraphNode : public UEdGraphNode
public:
UEdComboActionGraphNode();
void SetComboActionGraphNode(UComboActionGraphNode *NewNode);
class UEdComboActionGraph *GetEdComboActionGraph() const;
virtual void AllocateDefaultPins() override;

View File

@ -0,0 +1,131 @@
#include "SEdComboActionGraphEdge.h"
#include "ConnectionDrawingPolicy.h"
#include "SGraphPanel.h"
#include "Ed/EdComboActionGraphEdge.h"
#include "Ed/EdComboActionGraphNode.h"
#include "Widgets/Images/SImage.h"
#define LOCTEXT_NAMESPACE "SEdComboActionGraphEdge"
void SEdComboActionGraphEdge::Construct(const FArguments &InArgs, UEdComboActionGraphEdge *InNode)
{
this->GraphNode = InNode;
this->UpdateGraphNode();
}
bool SEdComboActionGraphEdge::RequiresSecondPassLayout() const
{
return true;
}
void SEdComboActionGraphEdge::PerformSecondPassLayout(const TMap<UObject*, TSharedRef<SNode>>& NodeToWidgetLookup) const
{
UEdComboActionGraphEdge *EdgeNode = CastChecked<UEdComboActionGraphEdge>(GraphNode);
FGeometry StartGeom;
FGeometry EndGeom;
UEdComboActionGraphNode *Start = EdgeNode->GetStartNode();
UEdComboActionGraphNode *End = EdgeNode->GetEndNode();
if (Start != nullptr && End != nullptr)
{
const TSharedRef<SNode> *pFromWidget = NodeToWidgetLookup.Find(Start);
const TSharedRef<SNode> *pToWidget = NodeToWidgetLookup.Find(End);
if (pFromWidget != nullptr && pToWidget != nullptr)
{
const TSharedRef<SNode>& FromWidget = *pFromWidget;
const TSharedRef<SNode>& ToWidget = *pToWidget;
StartGeom = FGeometry(FVector2D(Start->NodePosX, Start->NodePosY), FVector2D::ZeroVector, FromWidget->GetDesiredSize(), 1.0f);
EndGeom = FGeometry(FVector2D(End->NodePosX, End->NodePosY), FVector2D::ZeroVector, ToWidget->GetDesiredSize(), 1.0f);
}
}
PositionBetweenTwoNodesWithOffset(StartGeom, EndGeom, 0, 1);
}
void SEdComboActionGraphEdge::UpdateGraphNode()
{
InputPins.Empty();
OutputPins.Empty();
RightNodeBox.Reset();
LeftNodeBox.Reset();
this->ContentScale.Bind( this, &SGraphNode::GetContentScale );
this->GetOrAddSlot( ENodeZone::Center )
.HAlign(HAlign_Center)
.VAlign(VAlign_Center)
[
SNew(SOverlay)
/*+ SOverlay::Slot()
[
SNew(SImage)
.Image(FAppStyle::GetBrush("Graph.TransitionNode.ColorSpill"))
.ColorAndOpacity(this, &SEdComboActionGraphEdge::GetEdgeColor)
]*/
+ SOverlay::Slot()
[
SNew(SImage)
.Image(FAppStyle::GetBrush("GraphEditor.RefPinIcon"))
.ColorAndOpacity(this, &SEdComboActionGraphEdge::GetEdgeColor)
]
];
}
void SEdComboActionGraphEdge::PositionBetweenTwoNodesWithOffset(const FGeometry& StartGeom, const FGeometry& EndGeom, int32 NodeIndex, int32 MaxNodes) const
{
// Get a reasonable seed point (halfway between the boxes)
const FVector2D StartCenter = FGeometryHelper::CenterOf(StartGeom);
const FVector2D EndCenter = FGeometryHelper::CenterOf(EndGeom);
const FVector2D SeedPoint = (StartCenter + EndCenter) * 0.5f;
// Find the (approximate) closest points between the two boxes
const FVector2D StartAnchorPoint = FGeometryHelper::FindClosestPointOnGeom(StartGeom, SeedPoint);
const FVector2D EndAnchorPoint = FGeometryHelper::FindClosestPointOnGeom(EndGeom, SeedPoint);
// Position ourselves halfway along the connecting line between the nodes, elevated away perpendicular to the direction of the line
const float Height = 30.0f;
const FVector2D DesiredNodeSize = GetDesiredSize();
FVector2D DeltaPos(EndAnchorPoint - StartAnchorPoint);
if (DeltaPos.IsNearlyZero())
{
DeltaPos = FVector2D(10.0f, 0.0f);
}
const FVector2D Normal = FVector2D(DeltaPos.Y, -DeltaPos.X).GetSafeNormal();
const FVector2D NewCenter = StartAnchorPoint + (0.5f * DeltaPos) + (Height * Normal);
FVector2D DeltaNormal = DeltaPos.GetSafeNormal();
// Calculate node offset in the case of multiple transitions between the same two nodes
// MultiNodeOffset: the offset where 0 is the centre of the transition, -1 is 1 <size of node>
// towards the PrevStateNode and +1 is 1 <size of node> towards the NextStateNode.
const float MutliNodeSpace = 0.2f; // Space between multiple transition nodes (in units of <size of node> )
const float MultiNodeStep = (1.f + MutliNodeSpace); //Step between node centres (Size of node + size of node spacer)
const float MultiNodeStart = -((MaxNodes - 1) * MultiNodeStep) / 2.f;
const float MultiNodeOffset = MultiNodeStart + (NodeIndex * MultiNodeStep);
// Now we need to adjust the new center by the node size, zoom factor and multi node offset
const FVector2D NewCorner = NewCenter - (0.5f * DesiredNodeSize) + (DeltaNormal * MultiNodeOffset * DesiredNodeSize.Size());
GraphNode->NodePosX = NewCorner.X;
GraphNode->NodePosY = NewCorner.Y;
}
FSlateColor SEdComboActionGraphEdge::GetEdgeColor() const
{
return FLinearColor(0.9f, 0.9f, 0.9f, 1.0f);
}
#undef LOCTEXT_NAMESPACE

View File

@ -0,0 +1,33 @@
#pragma once
#include "CoreMinimal.h"
#include "Styling/SlateColor.h"
#include "Widgets/DeclarativeSyntaxSupport.h"
#include "Widgets/SWidget.h"
#include "SNodePanel.h"
#include "SGraphNode.h"
class SEdComboActionGraphEdge : public SGraphNode
{
public:
SLATE_BEGIN_ARGS(SEdComboActionGraphEdge){}
SLATE_END_ARGS()
void Construct(const FArguments &InArgs, class UEdComboActionGraphEdge *InNode);
virtual bool RequiresSecondPassLayout() const override;
virtual void PerformSecondPassLayout(const TMap<UObject*, TSharedRef<SNode> > &NodeToWidgetLookup) const override;
virtual void UpdateGraphNode() override;
// Calculate position for multiple nodes to be placed between a start and end point, by providing this nodes index and max expected nodes
void PositionBetweenTwoNodesWithOffset(const FGeometry &StartGeom, const FGeometry &EndGeom, int32 NodeIndex, int32 MaxNodes) const;
protected:
FSlateColor GetEdgeColor() const;
private:
TSharedPtr<STextEntryPopup> TextEntryWidget;
};

View File

@ -55,6 +55,20 @@ public:
virtual UObject *FactoryCreateNew(UClass *Class, UObject *InParent, FName Name, EObjectFlags Flags, UObject *Context, FFeedbackContext *Warn) override;
};
UCLASS()
class COMBOINPUTEDITOR_API UComboActionGraph_Factory : public UFactory
{
GENERATED_BODY()
public:
UComboActionGraph_Factory(const class FObjectInitializer &ObjectInitializer);
UPROPERTY(EditAnywhere, Category = "Combo Input|Action")
TSubclassOf<class UComboActionGraph> ComboActionGraphClass;
virtual UObject *FactoryCreateNew(UClass *Class, UObject *InParent, FName Name, EObjectFlags Flags, UObject *Context, FFeedbackContext *Warn) override;
};
class FComboInputEditorModule : public IModuleInterface
{
@ -63,7 +77,7 @@ public:
static bool IsAvailable() { return FModuleManager::Get().IsModuleLoaded("ComboInputEditor"); }
virtual void StartupModule() override;
virtual void ShutdownModule() override;
virtual void ShutdownModule() override{}
static EAssetTypeCategories::Type GetInputAssetsCategory() { return FComboInputEditorModule::ComboAssetsCategory; }
@ -77,8 +91,12 @@ private:
}
static EAssetTypeCategories::Type ComboAssetsCategory;
static EAssetTypeCategories::Type ComboActionGraphCategory;
TArray<TSharedPtr<IAssetTypeActions>> CreatedAssetTypeActions;
TSharedPtr<class FSlateStyleSet> ComboInputEditorStyleSet;
TSharedPtr<struct FGraphPanelNodeFactory> ComboActionGraphPanelNodeFactory;
TSharedPtr<class FAssetTypeActions_ComboActionGraph> ComboActionGraphAssetActions;
TSharedPtr<FSlateStyleSet> ComboActionGraphStyleSet;
};