923 lines
29 KiB
C++
923 lines
29 KiB
C++
// ©2023 Batty Bovine Productions, LLC. All Rights Reserved.
|
|
|
|
#include "AssetEditor_ComboActionGraph.h"
|
|
|
|
#include "ComboActionGraph.h"
|
|
#include "ComboActionGraphSchema.h"
|
|
#include "ComboInputEditor.h"
|
|
#include "EdGraphUtilities.h"
|
|
#include "GraphEditorActions.h"
|
|
|
|
#include "Ed/EdComboActionGraph.h"
|
|
#include "Ed/EdComboActionGraphEdge.h"
|
|
#include "Ed/EdComboActionGraphNode.h"
|
|
#include "Ed/FAssetEditorToolbarComboActionGraph.h"
|
|
#include "Ed/FComboActionGraphEditorCommands.h"
|
|
#include "Framework/Commands/GenericCommands.h"
|
|
#include "HAL/PlatformApplicationMisc.h"
|
|
#include "Kismet2/BlueprintEditorUtils.h"
|
|
#include "Layout/AssetEditorTabs.h"
|
|
#include "Layout/ComboActionGraphLayoutStrategy.h"
|
|
#include "Layout/ComboActionForceDirectedSolveLayoutStrategy.h"
|
|
#include "Layout/ComboActionTreeSolveLayoutStrategy.h"
|
|
#include "Nodes/ComboActionGraphNode.h"
|
|
#include "Popups/ComboInputPopup_GraphValidation.h"
|
|
#include "Search/ComboActionSearchUtils.h"
|
|
#include "Search/SComboActionSearch.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);
|
|
|
|
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();
|
|
|
|
if (!this->ToolbarBuilder.IsValid())
|
|
{
|
|
this->ToolbarBuilder = MakeShareable(new FAssetEditorToolbarComboActionGraph(SharedThis(this)));
|
|
}
|
|
|
|
this->BindCommands();
|
|
|
|
this->CreateInternalWidgets();
|
|
|
|
TSharedPtr<FExtender> ToolbarExtender = MakeShareable(new FExtender);
|
|
this->ToolbarBuilder->AddComboActionGraphToolbar(ToolbarExtender);
|
|
|
|
// Layout
|
|
const TSharedRef<FTabManager::FLayout> StandaloneDefaultLayout = FTabManager::NewLayout("Standalone_ComboActionGraphEditor_LayoutV0.3")
|
|
->AddArea
|
|
(
|
|
FTabManager::NewPrimaryArea()->SetOrientation(EOrientation::Orient_Vertical)
|
|
->Split
|
|
(
|
|
FTabManager::NewSplitter()->SetOrientation(EOrientation::Orient_Horizontal)->SetSizeCoefficient(0.9f)
|
|
->Split
|
|
(
|
|
FTabManager::NewStack()
|
|
->SetSizeCoefficient(3.f)
|
|
->AddTab(FAssetEditorTabs_ComboActionGraph::ViewportID, ETabState::OpenedTab)->SetHideTabWell(true)
|
|
)
|
|
->Split
|
|
(
|
|
FTabManager::NewSplitter()->SetOrientation(EOrientation::Orient_Vertical)
|
|
->Split
|
|
(
|
|
FTabManager::NewSplitter()->SetOrientation(EOrientation::Orient_Vertical)
|
|
->Split
|
|
(
|
|
FTabManager::NewStack()
|
|
->SetSizeCoefficient(0.9f)
|
|
->AddTab(FAssetEditorTabs_ComboActionGraph::ComboActionGraphPropertyID, ETabState::OpenedTab)->SetHideTabWell(true)
|
|
)
|
|
|
|
->Split
|
|
(
|
|
FTabManager::NewStack()
|
|
->SetSizeCoefficient(0.3f)
|
|
->AddTab(FAssetEditorTabs_ComboActionGraph::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)
|
|
{
|
|
this->WorkspaceMenuCategory = InTabManager->AddLocalWorkspaceMenuCategory(LOCTEXT("WorkspaceMenu_ComboActionTreeEditor", "Combo Action Tree Editor"));
|
|
auto WorkspaceMenuCategoryRef = this->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::ComboActionGraphPropertyID, 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(EAssetEditorCloseReason InCloseReason)
|
|
{
|
|
const bool bSatisfied = FAssetEditorToolkit::CloseWindow(InCloseReason);
|
|
|
|
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 || 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;
|
|
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(this->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().GetComboInputEditorStyleSet()->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)
|
|
);
|
|
}
|
|
|
|
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)
|
|
);
|
|
}
|
|
|
|
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::SelectAllNodes()
|
|
{
|
|
TSharedPtr<SGraphEditor> CurrentGraphEditor = this->GetCurrentGraphEditor();
|
|
if (CurrentGraphEditor.IsValid())
|
|
{
|
|
CurrentGraphEditor->SelectAllNodes();
|
|
}
|
|
}
|
|
|
|
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() const
|
|
{
|
|
// 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();
|
|
}
|
|
|
|
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() const
|
|
{
|
|
// 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())
|
|
{
|
|
this->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
|
|
{
|
|
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::AutoArrange()
|
|
{
|
|
// For now, auto-arrange is broken. Just in case it can be activated by accident,
|
|
// show a popup saying as much if an auto-arrange is attempted.
|
|
TArray<FText> ValidationMessages;
|
|
ValidationMessages.Add(LOCTEXT("AssetEditor_ComboActionGraph_AutoArrangeDisabled", "Auto-arrange is currently broken."));
|
|
ComboInputPopup_GraphValidation::Open(ValidationMessages);
|
|
|
|
//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, UComboActionTreeSolveLayoutStrategy::StaticClass());
|
|
// break;
|
|
// case EComboActionAutoLayoutStrategyType::ForceDirected:
|
|
// LayoutStrategy = NewObject<UComboActionGraphLayoutStrategy>(EdGraph, UComboActionForceDirectedSolveLayoutStrategy::StaticClass());
|
|
// break;
|
|
// default:
|
|
// break;
|
|
//}
|
|
|
|
//if (LayoutStrategy != nullptr)
|
|
//{
|
|
// LayoutStrategy->Layout(EdGraph);
|
|
// LayoutStrategy->ConditionalBeginDestroy();
|
|
//}
|
|
//else
|
|
//{
|
|
// UE_LOG(LogAssetEditorComboActionGraph, 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)
|
|
{
|
|
this->ValidationWindow = ComboInputPopup_GraphValidation::Open(ValidationMessages);
|
|
}
|
|
else
|
|
{
|
|
ValidationMessages.Empty();
|
|
this->ValidationWindow = ComboInputPopup_GraphValidation::Open(ValidationMessages);
|
|
}
|
|
}
|
|
|
|
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"))
|
|
[
|
|
this->PropertyWidget.ToSharedRef()
|
|
];
|
|
|
|
DockTab->SetTabIcon(FAppStyle::GetBrush("LevelEditor.Tabs.Details"));
|
|
return DockTab;
|
|
}
|
|
|
|
TSharedRef<SDockTab> FAssetEditor_ComboActionGraph::SpawnTab_Search(const FSpawnTabArgs &Args)
|
|
{
|
|
check(Args.GetTabId() == FAssetEditorTabs_ComboActionGraph::SearchToolbarID);
|
|
|
|
auto DockTab = SNew(SDockTab)
|
|
.Label(LOCTEXT("Search_Title", "Search"))
|
|
[
|
|
this->FindResultsView.ToSharedRef()
|
|
];
|
|
|
|
DockTab->SetTabIcon(FAppStyle::GetBrush("Kismet.Tabs.FindResults"));
|
|
return DockTab;
|
|
}
|
|
|
|
#undef LOCTEXT_NAMESPACE
|
|
|