diff --git a/Source/Flow/Private/FlowAsset.cpp b/Source/Flow/Private/FlowAsset.cpp index a6d32fb4..23450bff 100644 --- a/Source/Flow/Private/FlowAsset.cpp +++ b/Source/Flow/Private/FlowAsset.cpp @@ -1010,11 +1010,27 @@ void UFlowAsset::PreStartFlow() #endif } -void UFlowAsset::StartFlow(IFlowDataPinValueSupplierInterface* DataPinValueSupplier) +void UFlowAsset::StartFlow(IFlowDataPinValueSupplierInterface* DataPinValueSupplier /*= nullptr*/, const FGuid& StartingNodeGuid /*= FGuid()*/) { PreStartFlow(); - if (UFlowNode* ConnectedEntryNode = GetDefaultEntryNode()) + if (StartingNodeGuid.IsValid()) + { + if (UFlowNode* StartingNode = Nodes.FindRef(StartingNodeGuid)) + { + RecordedNodes.Add(StartingNode); + + if (StartingNode->GetInputPins().Num() > 0) + { + StartingNode->TriggerInput(StartingNode->GetInputPins()[0].PinName); + } + else + { + StartingNode->TriggerFirstOutput(true); + } + } + } + else if (UFlowNode* ConnectedEntryNode = GetDefaultEntryNode()) { RecordedNodes.Add(ConnectedEntryNode); diff --git a/Source/Flow/Private/FlowSubsystem.cpp b/Source/Flow/Private/FlowSubsystem.cpp index 70a88eaf..ac864142 100644 --- a/Source/Flow/Private/FlowSubsystem.cpp +++ b/Source/Flow/Private/FlowSubsystem.cpp @@ -76,13 +76,13 @@ void UFlowSubsystem::AbortActiveFlows() RootInstances.Empty(); } -void UFlowSubsystem::StartRootFlow(UObject* Owner, UFlowAsset* FlowAsset, const TScriptInterface DataPinValueSupplier, const bool bAllowMultipleInstances) +void UFlowSubsystem::StartRootFlow(UObject* Owner, UFlowAsset* FlowAsset, const TScriptInterface DataPinValueSupplier, const bool bAllowMultipleInstances, const FGuid& StartingNodeGuid = FGuid()) { if (FlowAsset) { if (UFlowAsset* NewFlow = CreateRootFlow(Owner, FlowAsset, bAllowMultipleInstances)) { - NewFlow->StartFlow(DataPinValueSupplier.GetInterface()); + NewFlow->StartFlow(DataPinValueSupplier.GetInterface(), StartingNodeGuid); } } #if WITH_EDITOR diff --git a/Source/Flow/Public/FlowAsset.h b/Source/Flow/Public/FlowAsset.h index ee470558..22a3502e 100644 --- a/Source/Flow/Public/FlowAsset.h +++ b/Source/Flow/Public/FlowAsset.h @@ -348,7 +348,7 @@ class FLOW_API UFlowAsset : public UObject virtual void PreloadNodes() {} virtual void PreStartFlow(); - virtual void StartFlow(IFlowDataPinValueSupplierInterface* DataPinValueSupplier = nullptr); + virtual void StartFlow(IFlowDataPinValueSupplierInterface* DataPinValueSupplier = nullptr, const FGuid& StartingNodeGuid = FGuid()); virtual void FinishFlow(const EFlowFinishPolicy InFinishPolicy, const bool bRemoveInstance = true); diff --git a/Source/Flow/Public/FlowSubsystem.h b/Source/Flow/Public/FlowSubsystem.h index 49274221..5a06b7bf 100644 --- a/Source/Flow/Public/FlowSubsystem.h +++ b/Source/Flow/Public/FlowSubsystem.h @@ -74,7 +74,7 @@ class FLOW_API UFlowSubsystem : public UGameInstanceSubsystem /* Start the root Flow, graph that will eventually instantiate next Flow Graphs through the SubGraph node */ UFUNCTION(BlueprintCallable, Category = "FlowSubsystem", meta = (DefaultToSelf = "Owner")) - virtual void StartRootFlow(UObject* Owner, UFlowAsset* FlowAsset, const TScriptInterface DataPinValueSupplier, const bool bAllowMultipleInstances = true); + virtual void StartRootFlow(UObject* Owner, UFlowAsset* FlowAsset, const TScriptInterface DataPinValueSupplier, const bool bAllowMultipleInstances = true, const FGuid& StartingNodeGuid = FGuid()); virtual UFlowAsset* CreateRootFlow(UObject* Owner, UFlowAsset* FlowAsset, const bool bAllowMultipleInstances = true, const FString& NewInstanceName = FString()); diff --git a/Source/FlowEditor/Private/FlowEditorCommands.cpp b/Source/FlowEditor/Private/FlowEditorCommands.cpp index 63c3b64a..0ab28b0f 100644 --- a/Source/FlowEditor/Private/FlowEditorCommands.cpp +++ b/Source/FlowEditor/Private/FlowEditorCommands.cpp @@ -57,6 +57,7 @@ void FFlowGraphCommands::RegisterCommands() UI_COMMAND(FocusViewport, "Focus Viewport", "Focus viewport on actor assigned to the node", EUserInterfaceActionType::Button, FInputChord()); UI_COMMAND(JumpToNodeDefinition, "Jump to Node Definition", "Jump to the node definition", EUserInterfaceActionType::Button, FInputChord()); + UI_COMMAND(RunFromNode, "Run from this node", "Run the flow starting from this node", EUserInterfaceActionType::Button, FInputChord()); } FFlowSpawnNodeCommands::FFlowSpawnNodeCommands() diff --git a/Source/FlowEditor/Private/Graph/FlowGraphEditor.cpp b/Source/FlowEditor/Private/Graph/FlowGraphEditor.cpp index 4d14f5b5..88973717 100644 --- a/Source/FlowEditor/Private/Graph/FlowGraphEditor.cpp +++ b/Source/FlowEditor/Private/Graph/FlowGraphEditor.cpp @@ -4,9 +4,13 @@ #include "Asset/FlowAssetEditor.h" #include "FlowEditorCommands.h" +#include "FlowSubsystem.h" +#include "Graph/FlowGraphSchema.h" #include "Graph/FlowGraphSchema_Actions.h" #include "Graph/Nodes/FlowGraphNode.h" +#include "Engine/GameInstance.h" + #include "Debugger/FlowDebuggerSubsystem.h" #include "EdGraphUtilities.h" @@ -250,6 +254,10 @@ void SFlowGraphEditor::BindGraphCommands() FExecuteAction::CreateSP(this, &SFlowGraphEditor::JumpToNodeDefinition), FCanExecuteAction::CreateSP(this, &SFlowGraphEditor::CanJumpToNodeDefinition)); + CommandList->MapAction(FlowGraphCommands.RunFromNode, + FExecuteAction::CreateSP(this, &SFlowGraphEditor::RunFromNode), + FCanExecuteAction::CreateSP(this, &SFlowGraphEditor::CanRunFromNode)); + // Organisation Commands CommandList->MapAction(GraphEditorCommands.AlignNodesTop, FExecuteAction::CreateSP(this, &SFlowGraphEditor::OnAlignTop)); @@ -1534,7 +1542,34 @@ void SFlowGraphEditor::JumpToNodeDefinition() const bool SFlowGraphEditor::CanJumpToNodeDefinition() const { - return GetSelectedFlowNodes().Num() == 1; + return GetSelectedFlowNodes().Num() == 1 && GetSelectedFlowNodes().Array()[0]->CanJumpToDefinition(); +} + +void SFlowGraphEditor::RunFromNode() const +{ + if (IsPIE()) + { + const TSet SelectedNodes = GetSelectedFlowNodes(); + if (SelectedNodes.Num() == 1) + { + if (const UFlowGraphNode* SelectedNode = SelectedNodes.Array()[0]) + { + if (const UFlowNode* HelperNode = Cast(SelectedNode->GetFlowNodeBase())) + { + if (UFlowSubsystem* FlowSubsystem = GEditor->PlayWorld->GetGameInstance()->GetSubsystem()) + { + FlowSubsystem->AbortActiveFlows(); + FlowSubsystem->StartRootFlow(GEditor->PlayWorld->GetGameInstance(), const_cast(FlowAsset.Get()), true, HelperNode->GetGuid()); + } + } + } + } + } +} + +bool SFlowGraphEditor::CanRunFromNode() const +{ + return IsPIE() && GetSelectedFlowNodes().Num() == 1; } #undef LOCTEXT_NAMESPACE diff --git a/Source/FlowEditor/Private/Graph/Nodes/FlowGraphNode.cpp b/Source/FlowEditor/Private/Graph/Nodes/FlowGraphNode.cpp index 9864a54e..5d4ca487 100644 --- a/Source/FlowEditor/Private/Graph/Nodes/FlowGraphNode.cpp +++ b/Source/FlowEditor/Private/Graph/Nodes/FlowGraphNode.cpp @@ -10,6 +10,7 @@ #include "FlowEditorCommands.h" #include "Graph/FlowGraph.h" +#include "Graph/FlowGraphEditor.h" #include "Graph/FlowGraphEditorSettings.h" #include "Graph/FlowGraphSchema.h" #include "Graph/FlowGraphSettings.h" @@ -584,6 +585,10 @@ void UFlowGraphNode::GetNodeContextMenuActions(class UToolMenu* Menu, class UGra { Section.AddMenuEntry(FlowGraphCommands.JumpToNodeDefinition); } + if (SFlowGraphEditor::IsPIE()) + { + Section.AddMenuEntry(FlowGraphCommands.RunFromNode); + } } { diff --git a/Source/FlowEditor/Public/FlowEditorCommands.h b/Source/FlowEditor/Public/FlowEditorCommands.h index 2629a4ad..5c907555 100644 --- a/Source/FlowEditor/Public/FlowEditorCommands.h +++ b/Source/FlowEditor/Public/FlowEditorCommands.h @@ -58,6 +58,7 @@ class FLOWEDITOR_API FFlowGraphCommands : public TCommands /** Jumps */ TSharedPtr FocusViewport; TSharedPtr JumpToNodeDefinition; + TSharedPtr RunFromNode; virtual void RegisterCommands() override; }; diff --git a/Source/FlowEditor/Public/Graph/FlowGraphEditor.h b/Source/FlowEditor/Public/Graph/FlowGraphEditor.h index 15c6ee9b..5b87c5c6 100644 --- a/Source/FlowEditor/Public/Graph/FlowGraphEditor.h +++ b/Source/FlowEditor/Public/Graph/FlowGraphEditor.h @@ -168,4 +168,7 @@ class FLOWEDITOR_API SFlowGraphEditor : public SGraphEditor void JumpToNodeDefinition() const; bool CanJumpToNodeDefinition() const; + + void RunFromNode() const; + bool CanRunFromNode() const; }; \ No newline at end of file