Untitled
//MultiGate.h// // Copyright https://github.com/MothCocoon/FlowGraph/graphs/contributors #pragma once #include "Nodes/FlowNode.h" #include "FlowNode_ExecutionMultiGate.generated.h" /** * Executes a series of pins in order */ UCLASS(NotBlueprintable, meta = (DisplayName = "Multi Gate", Keywords = "series, loop, random")) class FLOW_API UFlowNode_ExecutionMultiGate final : public UFlowNode { GENERATED_UCLASS_BODY() UPROPERTY(EditAnywhere, Category = "MultiGate", meta = (EditCondition = "bParallel==false")) bool bRandom; // Allow executing output pins again, without triggering Reset pin // If set to False, every output pin can be triggered only once UPROPERTY(EditAnywhere, Category = "MultiGate") bool bLoop; //Allow the execution of the outputs in parallel UPROPERTY(EditAnywhere, Category = "MultiGate") bool bParallel; UPROPERTY(EditAnywhere, Category = "MultiGate") int32 StartIndex; private: UPROPERTY(SaveGame) int32 NextOutput; UPROPERTY(SaveGame) TArray<bool> Completed; public: #if WITH_EDITOR virtual bool CanUserAddOutput() const override { return true; } #endif protected: virtual void ExecuteInput(const FName& PinName) override; virtual void Cleanup() override; #if WITH_EDITOR virtual FString GetNodeDescription() const override; #endif }; //MultiGate.cpp// // Copyright https://github.com/MothCocoon/FlowGraph/graphs/contributors #include "Nodes/Route/FlowNode_ExecutionMultiGate.h" UFlowNode_ExecutionMultiGate::UFlowNode_ExecutionMultiGate(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) , StartIndex(INDEX_NONE) { #if WITH_EDITOR Category = TEXT("Route"); NodeStyle = EFlowNodeStyle::Logic; #endif FString ResetPinTooltip = TEXT("Finish work of this node."); ResetPinTooltip += LINE_TERMINATOR; ResetPinTooltip += TEXT("Calling In input will start triggering output pins once again."); InputPins.Add(FFlowPin(TEXT("Stop"))); InputPins.Add(FFlowPin(TEXT("Reset"), ResetPinTooltip)); AllowedSignalModes = {EFlowSignalMode::Enabled, EFlowSignalMode::Disabled}; OutputPins.Empty(); SetNumberedOutputPins(0, 1); OutputPins.Add(FFlowPin(TEXT("Completed"))); OutputPins.Add(FFlowPin(TEXT("Stopped"))); } void UFlowNode_ExecutionMultiGate::ExecuteInput(const FName& PinName) { if (PinName == DefaultInputPin.PinName) { if (Completed.Num() == 0) { Completed.Init(false, OutputPins.Num()); } if (!Completed.Contains(false)) { return; } const bool bUseStartIndex = !Completed.Contains(true) && Completed.IsValidIndex(StartIndex); if (bParallel) { // Ejecutar todas las salidas en paralelo directamente for (const FFlowPin& Output : OutputPins) { TriggerOutput(Output.PinName, false); } // Llamar al output "Completed" cuando se completan todas las salidas en paralelo TriggerOutput(TEXT("Completed"), false); } if (bRandom) { int32 Index; if (bUseStartIndex) { Index = StartIndex; } else { TArray<int32> AvailableIndexes; AvailableIndexes.Reserve(Completed.Num()); // todo for (int32 i = 0; i < Completed.Num(); i++) { if (Completed[i] == false) { AvailableIndexes.Emplace(i); } } const int32 Random = FMath::RandRange(0, AvailableIndexes.Num() - 1); Index = AvailableIndexes[Random]; } Completed[Index] = true; TriggerOutput(OutputPins[Index].PinName, false); } else { if (bUseStartIndex) { NextOutput = StartIndex; } const int32 CurrentOutput = NextOutput; // We have to calculate NextOutput before TriggerOutput(..) // TriggerOutput may call Reset and Cleanup NextOutput = ++NextOutput % OutputPins.Num(); Completed[CurrentOutput] = true; TriggerOutput(OutputPins[CurrentOutput].PinName, false); } if (!Completed.Contains(false) && bLoop) { Finish(); } } else if (PinName == TEXT("Reset")) { Finish(); } } void UFlowNode_ExecutionMultiGate::Cleanup() { NextOutput = 0; Completed.Reset(); } #if WITH_EDITOR FString UFlowNode_ExecutionMultiGate::GetNodeDescription() const { FString Result; Result.Reserve(128); if (bRandom) { Result.Append(TEXT("Random")); } if (bParallel) { Result.Append(TEXT("Parallel")); } if (bRandom && bLoop) { Result.Append(TEXT(", ")); } if (bLoop) { Result.Append(TEXT("Loop")); } if (StartIndex != INDEX_NONE) { if (bRandom || bLoop) { Result.Append(TEXT(", ")); } if (OutputPins.IsValidIndex(StartIndex)) { Result.Appendf(TEXT("Start Index: %d"), StartIndex); } else { Result.Append(TEXT("StartIndex: Invalid")); } } return Result; } #endif
Leave a Comment