From cee9454b38bff5e73eb68427c2b18b5a0043c201 Mon Sep 17 00:00:00 2001 From: Damian Nowakowski Date: Fri, 30 May 2025 13:42:35 +0000 Subject: [PATCH 01/13] Add FindActionByLabel function to locate actions by label in ECF subsystem and library --- .../Private/BP/ECFBPLibrary.cpp | 5 ++++ .../EnhancedCodeFlow/Private/ECFSubsystem.cpp | 25 +++++++++++++++++++ .../Private/EnhancedCodeFlow.cpp | 7 ++++++ .../EnhancedCodeFlow/Public/BP/ECFBPLibrary.h | 6 +++++ .../CodeFlowActions/ECFCustomTimeline.h | 2 +- .../ECFCustomTimelineLinearColor.h | 2 +- .../CodeFlowActions/ECFCustomTimelineVector.h | 2 +- .../Public/CodeFlowActions/ECFDelay.h | 4 +-- .../Public/CodeFlowActions/ECFDelayTicks.h | 2 +- .../Public/CodeFlowActions/ECFDoNTimes.h | 2 +- .../CodeFlowActions/ECFDoNoMoreThanXTime.h | 2 +- .../Public/CodeFlowActions/ECFDoOnce.h | 2 +- .../Public/CodeFlowActions/ECFRunAsyncThen.h | 6 ++--- .../Public/CodeFlowActions/ECFTicker.h | 2 +- .../Public/CodeFlowActions/ECFTimeLock.h | 2 +- .../Public/CodeFlowActions/ECFTimeline.h | 2 +- .../CodeFlowActions/ECFTimelineLinearColor.h | 2 +- .../CodeFlowActions/ECFTimelineVector.h | 2 +- .../CodeFlowActions/ECFWaitAndExecute.h | 12 ++++----- .../CodeFlowActions/ECFWhileTrueExecute.h | 2 +- .../Public/ECFActionSettings.h | 24 ++++++++++-------- Source/EnhancedCodeFlow/Public/ECFSubsystem.h | 4 +++ 22 files changed, 85 insertions(+), 34 deletions(-) diff --git a/Source/EnhancedCodeFlow/Private/BP/ECFBPLibrary.cpp b/Source/EnhancedCodeFlow/Private/BP/ECFBPLibrary.cpp index 20fcbcc..5ef7544 100644 --- a/Source/EnhancedCodeFlow/Private/BP/ECFBPLibrary.cpp +++ b/Source/EnhancedCodeFlow/Private/BP/ECFBPLibrary.cpp @@ -184,4 +184,9 @@ FString UECFBPLibrary::Conv_ECFInstanceIdToString(const FECFInstanceIdBP& Instan /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ +FECFHandleBP UECFBPLibrary::FindActionByLabel(const UObject* WorldContextObject, const FString& Label) +{ + return FECFHandleBP(FFlow::FindActionByLabel(WorldContextObject, Label)); +} + ECF_PRAGMA_ENABLE_OPTIMIZATION \ No newline at end of file diff --git a/Source/EnhancedCodeFlow/Private/ECFSubsystem.cpp b/Source/EnhancedCodeFlow/Private/ECFSubsystem.cpp index e0b5516..abb1915 100644 --- a/Source/EnhancedCodeFlow/Private/ECFSubsystem.cpp +++ b/Source/EnhancedCodeFlow/Private/ECFSubsystem.cpp @@ -138,6 +138,31 @@ UECFActionBase* UECFSubsystem::FindAction(const FECFHandle& HandleId) const return nullptr; } +FECFHandle UECFSubsystem::FindActionByLabel(const FString& Label) const +{ + if (Label.IsEmpty()) + { + return FECFHandle(); + } + // Search in active actions + for (UECFActionBase* Action : Actions) + { + if (IsActionValid(Action) && Action->Settings.Label == Label) + { + return Action->GetHandleId(); + } + } + // Search in pending actions + for (UECFActionBase* PendingAction : PendingAddActions) + { + if (IsActionValid(PendingAction) && PendingAction->Settings.Label == Label) + { + return PendingAction->GetHandleId(); + } + } + return FECFHandle(); +} + void UECFSubsystem::PauseAction(const FECFHandle& HandleId) { if (UECFActionBase* ActionFound = FindAction(HandleId)) diff --git a/Source/EnhancedCodeFlow/Private/EnhancedCodeFlow.cpp b/Source/EnhancedCodeFlow/Private/EnhancedCodeFlow.cpp index a081a39..e97cad9 100644 --- a/Source/EnhancedCodeFlow/Private/EnhancedCodeFlow.cpp +++ b/Source/EnhancedCodeFlow/Private/EnhancedCodeFlow.cpp @@ -589,4 +589,11 @@ void FEnhancedCodeFlow::RemoveAllRunAsyncAndWait(const UObject* WorldContextObje ECF->RemoveActionsOfClass(bComplete, InOwner); } +FECFHandle FEnhancedCodeFlow::FindActionByLabel(const UObject* WorldContextObject, const FString& Label) +{ + if (UECFSubsystem* ECF = UECFSubsystem::Get(WorldContextObject)) + return ECF->FindActionByLabel(Label); + return FECFHandle(); +} + ECF_PRAGMA_ENABLE_OPTIMIZATION diff --git a/Source/EnhancedCodeFlow/Public/BP/ECFBPLibrary.h b/Source/EnhancedCodeFlow/Public/BP/ECFBPLibrary.h index 93df246..7d13b15 100644 --- a/Source/EnhancedCodeFlow/Public/BP/ECFBPLibrary.h +++ b/Source/EnhancedCodeFlow/Public/BP/ECFBPLibrary.h @@ -261,5 +261,11 @@ class ENHANCEDCODEFLOW_API UECFBPLibrary : public UBlueprintFunctionLibrary UFUNCTION(BlueprintPure, meta = (DisplayName = "ToString (FECFInstanceIdBP)", CompactNodeTitle = "->", BlueprintAutocast), Category = "ECF") static FString Conv_ECFInstanceIdToString(const FECFInstanceIdBP& InstanceId); + /** + * Finds the first running or pending action with the given Label and returns its handle (for Blueprints). + */ + UFUNCTION(BlueprintPure, meta = (WorldContext = "WorldContextObject", DisplayName = "ECF - Find Action By Label"), Category = "ECF") + static FECFHandleBP FindActionByLabel(const UObject* WorldContextObject, const FString& Label); + /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ }; diff --git a/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFCustomTimeline.h b/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFCustomTimeline.h index 666a44c..3935492 100644 --- a/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFCustomTimeline.h +++ b/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFCustomTimeline.h @@ -46,7 +46,7 @@ class ENHANCEDCODEFLOW_API UECFCustomTimeline : public UECFActionBase else { #if ECF_LOGS - UE_LOG(LogECF, Error, TEXT("ECF - custom timeline failed to start. Are you sure Tick Function and Curve are set properly?")); + UE_LOG(LogECF, Error, TEXT("ECF - [%s] custom timeline failed to start. Are you sure Tick Function and Curve are set properly?"), *Settings.Label); #endif return false; } diff --git a/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFCustomTimelineLinearColor.h b/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFCustomTimelineLinearColor.h index 5392eee..dba2267 100644 --- a/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFCustomTimelineLinearColor.h +++ b/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFCustomTimelineLinearColor.h @@ -46,7 +46,7 @@ class ENHANCEDCODEFLOW_API UECFCustomTimelineLinearColor : public UECFActionBase else { #if ECF_LOGS - UE_LOG(LogECF, Error, TEXT("ECF - custom timeline LinearColor failed to start. Are you sure Tick Function and Curve are set properly?")); + UE_LOG(LogECF, Error, TEXT("ECF - [%s] custom timeline LinearColor failed to start. Are you sure Tick Function and Curve are set properly?"), *Settings.Label); #endif return false; } diff --git a/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFCustomTimelineVector.h b/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFCustomTimelineVector.h index 9c4a57e..b5d8c91 100644 --- a/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFCustomTimelineVector.h +++ b/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFCustomTimelineVector.h @@ -46,7 +46,7 @@ class ENHANCEDCODEFLOW_API UECFCustomTimelineVector : public UECFActionBase else { #if ECF_LOGS - UE_LOG(LogECF, Error, TEXT("ECF - custom timeline vector failed to start. Are you sure Tick Function and Curve are set properly?")); + UE_LOG(LogECF, Error, TEXT("ECF - [%s] custom timeline vector failed to start. Are you sure Tick Function and Curve are set properly?"), *Settings.Label); #endif return false; } diff --git a/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFDelay.h b/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFDelay.h index c6e7327..28ff7b7 100644 --- a/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFDelay.h +++ b/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFDelay.h @@ -37,7 +37,7 @@ class ENHANCEDCODEFLOW_API UECFDelay : public UECFActionBase else { #if ECF_LOGS - UE_LOG(LogECF, Error, TEXT("ECF - delay failed to start. Are you sure the DelayTime is not negative and Callback Function is set properly?")); + UE_LOG(LogECF, Error, TEXT("ECF - [%s] delay failed to start. Are you sure the DelayTime is not negative and Callback Function is set properly?"), *Settings.Label); #endif return false; } @@ -56,7 +56,7 @@ class ENHANCEDCODEFLOW_API UECFDelay : public UECFActionBase else { #if ECF_LOGS - UE_LOG(LogECF, Error, TEXT("ECF - delay failed to start. Are you sure the Callback Function is set properly?")); + UE_LOG(LogECF, Error, TEXT("ECF - [%s] delay failed to start. Are you sure the Callback Function is set properly?"), *Settings.Label); #endif return false; } diff --git a/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFDelayTicks.h b/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFDelayTicks.h index 5b82d70..5e56024 100644 --- a/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFDelayTicks.h +++ b/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFDelayTicks.h @@ -33,7 +33,7 @@ class ENHANCEDCODEFLOW_API UECFDelayTicks : public UECFActionBase else { #if ECF_LOGS - UE_LOG(LogECF, Error, TEXT("ECF - delay ticks failed to start. Are you sure the DelayTicks is not negative and Callback Function is set properly?")); + UE_LOG(LogECF, Error, TEXT("ECF - [%s] delay ticks failed to start. Are you sure the DelayTicks is not negative and Callback Function is set properly?"), *Settings.Label); #endif return false; } diff --git a/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFDoNTimes.h b/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFDoNTimes.h index 07eec3e..9e69bf1 100644 --- a/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFDoNTimes.h +++ b/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFDoNTimes.h @@ -32,7 +32,7 @@ class ENHANCEDCODEFLOW_API UECFDoNTimes : public UECFActionBase else { #if ECF_LOGS - UE_LOG(LogECF, Error, TEXT("ECF - DoNTimes failed to start. Are you sure Exec Fuinction and Times number are set properly?")); + UE_LOG(LogECF, Error, TEXT("ECF - [%s] Do N Times failed to start. Are you sure the Exec Function is set properly?"), *Settings.Label); #endif return false; } diff --git a/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFDoNoMoreThanXTime.h b/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFDoNoMoreThanXTime.h index 115f4ae..fa5b5e9 100644 --- a/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFDoNoMoreThanXTime.h +++ b/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFDoNoMoreThanXTime.h @@ -36,7 +36,7 @@ class ENHANCEDCODEFLOW_API UECFDoNoMoreThanXTime : public UECFActionBase else { #if ECF_LOGS - UE_LOG(LogECF, Error, TEXT("ECF - Do No More Than Times failed to start. Are you sure the Lock time and Max Execs Eneueud are greater than 0 and the Exec Function is set properly?")); + UE_LOG(LogECF, Error, TEXT("ECF - [%s] Do No More Than Times failed to start. Are you sure the Lock time and Max Execs Eneueud are greater than 0 and the Exec Function is set properly?"), *Settings.Label); #endif return false; } diff --git a/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFDoOnce.h b/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFDoOnce.h index ccbca4a..2cb813b 100644 --- a/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFDoOnce.h +++ b/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFDoOnce.h @@ -30,7 +30,7 @@ class ENHANCEDCODEFLOW_API UECFDoOnce : public UECFActionBase else { #if ECF_LOGS - UE_LOG(LogECF, Error, TEXT("ECF - do once failed to start. Are you sure the Exec Function is is set properly?")); + UE_LOG(LogECF, Error, TEXT("ECF - [%s] do once failed to start. Are you sure the Exec Function is is set properly?"), *Settings.Label); #endif return false; } diff --git a/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFRunAsyncThen.h b/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFRunAsyncThen.h index aa8e1c8..54595bd 100644 --- a/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFRunAsyncThen.h +++ b/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFRunAsyncThen.h @@ -81,7 +81,7 @@ class ENHANCEDCODEFLOW_API UECFRunAsyncThen : public UECFActionBase else { #if ECF_LOGS - UE_LOG(LogECF, Error, TEXT("ECF - Run Async Task and Run failed to start. Are you sure the AsyncTask and Function are set properly?")); + UE_LOG(LogECF, Error, TEXT("ECF - [%s] Run Async Task and Run failed to start. Are you sure the AsyncTask and Function are set properly?"), *Settings.Label); #endif return false; } @@ -100,7 +100,7 @@ class ENHANCEDCODEFLOW_API UECFRunAsyncThen : public UECFActionBase else { #if ECF_LOGS - UE_LOG(LogECF, Error, TEXT("ECF - Run Async Task and Run failed to start. Are you sure the Function is set properly?")); + UE_LOG(LogECF, Error, TEXT("ECF - [%s] Run Async Task and Run failed to start. Are you sure the Function is set properly?"), *Settings.Label); #endif return false; } @@ -119,7 +119,7 @@ class ENHANCEDCODEFLOW_API UECFRunAsyncThen : public UECFActionBase else { #if ECF_LOGS - UE_LOG(LogECF, Error, TEXT("ECF - Run Async Task and Run failed to start. Are you sure the Function is set properly?")); + UE_LOG(LogECF, Error, TEXT("ECF - [%s] Run Async Task and Run failed to start. Are you sure the Function is set properly?"), *Settings.Label); #endif return false; } diff --git a/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFTicker.h b/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFTicker.h index c9f0d24..e59ab88 100644 --- a/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFTicker.h +++ b/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFTicker.h @@ -43,7 +43,7 @@ class ENHANCEDCODEFLOW_API UECFTicker : public UECFActionBase else { #if ECF_LOGS - UE_LOG(LogECF, Error, TEXT("ECF - Ticker(2) failed to start. Are you sure the Ticking time and Ticking Function are set properly?")); + UE_LOG(LogECF, Error, TEXT("ECF - [%s] ticker failed to start. Are you sure the Ticking time is greater than 0 and Ticking Function are set properly?"), *Settings.Label); #endif return false; } diff --git a/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFTimeLock.h b/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFTimeLock.h index 9eea8b8..d370615 100644 --- a/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFTimeLock.h +++ b/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFTimeLock.h @@ -33,7 +33,7 @@ class ENHANCEDCODEFLOW_API UECFTimeLock : public UECFActionBase else { #if ECF_LOGS - UE_LOG(LogECF, Error, TEXT("ECF - Timelock failed to start. Are you sure the Lock time is greater than 0 and the Exec Function is set properly?")); + UE_LOG(LogECF, Error, TEXT("ECF - [%s] Timelock failed to start. Are you sure the Lock time is greater than 0 and the Exec Function is set properly?"), *Settings.Label); #endif return false; } diff --git a/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFTimeline.h b/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFTimeline.h index dd5fd19..b37917e 100644 --- a/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFTimeline.h +++ b/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFTimeline.h @@ -70,7 +70,7 @@ class ENHANCEDCODEFLOW_API UECFTimeline : public UECFActionBase else { #if ECF_LOGS - UE_LOG(LogECF, Error, TEXT("ECF - Timeline failed to start. Are you sure the Ticking time is greater than 0 and Ticking Function are set properly? /n Remember, that BlendExp must be different than zero and StartValue and StopValue must not be the same!")); + UE_LOG(LogECF, Error, TEXT("ECF - [%s] Timeline failed to start. Are you sure the Ticking time is greater than 0 and Ticking Function are set properly? /n Remember, that BlendExp must be different than zero and StartValue and StopValue must not be the same!"), *Settings.Label); #endif return false; } diff --git a/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFTimelineLinearColor.h b/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFTimelineLinearColor.h index 741821b..32d6ba0 100644 --- a/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFTimelineLinearColor.h +++ b/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFTimelineLinearColor.h @@ -70,7 +70,7 @@ class ENHANCEDCODEFLOW_API UECFTimelineLinearColor: public UECFActionBase else { #if ECF_LOGS - UE_LOG(LogECF, Error, TEXT("ECF - Timeline Linear Color failed to start. Are you sure the Ticking time is greater than 0 and Ticking Function are set properly? /n Remember, that BlendExp must be different than zero and StartValue and StopValue must not be the same!")); + UE_LOG(LogECF, Error, TEXT("ECF - [%s] Timeline Linear Color failed to start. Are you sure the Ticking time is greater than 0 and Ticking Function are set properly? /n Remember, that BlendExp must be different than zero and StartValue and StopValue must not be the same!"), *Settings.Label); #endif return false; } diff --git a/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFTimelineVector.h b/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFTimelineVector.h index f0e9b8e..aa4cb5a 100644 --- a/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFTimelineVector.h +++ b/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFTimelineVector.h @@ -70,7 +70,7 @@ class ENHANCEDCODEFLOW_API UECFTimelineVector : public UECFActionBase else { #if ECF_LOGS - UE_LOG(LogECF, Error, TEXT("ECF - Timeline Vector failed to start. Are you sure the Ticking time is greater than 0 and Ticking Function are set properly? /n Remember, that BlendExp must be different than zero and StartValue and StopValue must not be the same!")); + UE_LOG(LogECF, Error, TEXT("ECF - [%s] Timeline Vector failed to start. Are you sure the Ticking time is greater than 0 and Ticking Function are set properly? /n Remember, that BlendExp must be different than zero and StartValue and StopValue must not be the same!"), *Settings.Label); #endif return false; } diff --git a/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFWaitAndExecute.h b/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFWaitAndExecute.h index e9574fa..8871f97 100644 --- a/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFWaitAndExecute.h +++ b/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFWaitAndExecute.h @@ -60,7 +60,7 @@ class ENHANCEDCODEFLOW_API UECFWaitAndExecute : public UECFActionBase else { #if ECF_LOGS - UE_LOG(LogECF, Error, TEXT("ECF - Wait and Execute failed to start. Are you sure the Predicate and Function are set properly?")); + UE_LOG(LogECF, Error, TEXT("ECF - [%s] Wait and Execute failed to start. Are you sure the Predicate and Function are set properly?"), *Settings.Label); #endif return false; } @@ -82,7 +82,7 @@ class ENHANCEDCODEFLOW_API UECFWaitAndExecute : public UECFActionBase else { #if ECF_LOGS - UE_LOG(LogECF, Error, TEXT("ECF - Wait and Execute failed to start. Are you sure the Function is set properly?")); + UE_LOG(LogECF, Error, TEXT("ECF - [%s] Wait and Execute failed to start. Are you sure the Function is set properly?"), *Settings.Label); #endif return false; } @@ -104,7 +104,7 @@ class ENHANCEDCODEFLOW_API UECFWaitAndExecute : public UECFActionBase else { #if ECF_LOGS - UE_LOG(LogECF, Error, TEXT("ECF - Wait and Execute failed to start. Are you sure the Function is set properly?")); + UE_LOG(LogECF, Error, TEXT("ECF - [%s] Wait and Execute failed to start. Are you sure the Function is set properly?"), *Settings.Label); #endif return false; } @@ -131,7 +131,7 @@ class ENHANCEDCODEFLOW_API UECFWaitAndExecute : public UECFActionBase else { #if ECF_LOGS - UE_LOG(LogECF, Error, TEXT("ECF - Wait and Execute failed to start. Are you sure the Function is set properly?")); + UE_LOG(LogECF, Error, TEXT("ECF - [%s] Wait and Execute failed to start. Are you sure the Function is set properly?"), *Settings.Label); #endif return false; } @@ -153,7 +153,7 @@ class ENHANCEDCODEFLOW_API UECFWaitAndExecute : public UECFActionBase else { #if ECF_LOGS - UE_LOG(LogECF, Error, TEXT("ECF - Wait and Execute failed to start. Are you sure the Function is set properly?")); + UE_LOG(LogECF, Error, TEXT("ECF - [%s] Wait and Execute failed to start. Are you sure the Function is set properly?"), *Settings.Label); #endif return false; } @@ -180,7 +180,7 @@ class ENHANCEDCODEFLOW_API UECFWaitAndExecute : public UECFActionBase else { #if ECF_LOGS - UE_LOG(LogECF, Error, TEXT("ECF - Wait and Execute failed to start. Are you sure the Function is set properly?")); + UE_LOG(LogECF, Error, TEXT("ECF - [%s] Wait and Execute failed to start. Are you sure the Function is set properly?"), *Settings.Label); #endif return false; } diff --git a/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFWhileTrueExecute.h b/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFWhileTrueExecute.h index 88c2eb2..a8c6eef 100644 --- a/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFWhileTrueExecute.h +++ b/Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFWhileTrueExecute.h @@ -61,7 +61,7 @@ class ENHANCEDCODEFLOW_API UECFWhileTrueExecute : public UECFActionBase else { #if ECF_LOGS - UE_LOG(LogECF, Error, TEXT("ECF - While True Execute failed to start. Are you sure the Predicate and Function are set properly?")); + UE_LOG(LogECF, Error, TEXT("ECF - [%s] While True Execute failed to start. Are you sure the Predicate and Function are set properly?"), *Settings.Label); #endif return false; } diff --git a/Source/EnhancedCodeFlow/Public/ECFActionSettings.h b/Source/EnhancedCodeFlow/Public/ECFActionSettings.h index c62336e..071319f 100644 --- a/Source/EnhancedCodeFlow/Public/ECFActionSettings.h +++ b/Source/EnhancedCodeFlow/Public/ECFActionSettings.h @@ -15,19 +15,20 @@ struct ENHANCEDCODEFLOW_API FECFActionSettings FirstDelay(0.f), bIgnorePause(false), bIgnoreGlobalTimeDilation(false), - bStartPaused(false) + bStartPaused(false), + Label(TEXT("")) { } - FECFActionSettings(float InTickInterval, float InFirstDelay = 0.f, bool InIgnorePause = false, bool InIgnoreTimeDilation = false, bool InStartPaused = false) : + FECFActionSettings(float InTickInterval, float InFirstDelay = 0.f, bool InIgnorePause = false, bool InIgnoreTimeDilation = false, bool InStartPaused = false, const FString& InLabel = TEXT("")) : TickInterval(InTickInterval), FirstDelay(InFirstDelay), bIgnorePause(InIgnorePause), bIgnoreGlobalTimeDilation(InIgnoreTimeDilation), - bStartPaused(InStartPaused) + bStartPaused(InStartPaused), + Label(InLabel) { - } UPROPERTY(BlueprintReadWrite, Category = "ECF") @@ -44,11 +45,14 @@ struct ENHANCEDCODEFLOW_API FECFActionSettings UPROPERTY(BlueprintReadWrite, Category = "ECF") bool bStartPaused = false; + + UPROPERTY(BlueprintReadWrite, Category = "ECF") + FString Label; }; -#define ECF_TICKINTERVAL(_Interval) FECFActionSettings(_Interval, 0.f, false, false, false) -#define ECF_DELAYFIRST(_Delay) FECFActionSettings(0.f, _Delay, false, false, false) -#define ECF_IGNOREPAUSE FECFActionSettings(0.f, 0.f, true, false, false) -#define ECF_IGNORETIMEDILATION FECFActionSettings(0.f, 0.f, false, true, false) -#define ECF_IGNOREPAUSEDILATION FECFActionSettings(0.f, 0.f, true, true, false) -#define ECF_STARTPAUSED FECFActionSettings(0.f, 0.f, false, false, true) +#define ECF_TICKINTERVAL(_Interval) FECFActionSettings(_Interval, 0.f, false, false, false, TEXT("")) +#define ECF_DELAYFIRST(_Delay) FECFActionSettings(0.f, _Delay, false, false, false, TEXT("")) +#define ECF_IGNOREPAUSE FECFActionSettings(0.f, 0.f, true, false, false, TEXT("")) +#define ECF_IGNORETIMEDILATION FECFActionSettings(0.f, 0.f, false, true, false, TEXT("")) +#define ECF_IGNOREPAUSEDILATION FECFActionSettings(0.f, 0.f, true, true, false, TEXT("")) +#define ECF_STARTPAUSED FECFActionSettings(0.f, 0.f, false, false, true, TEXT("")) diff --git a/Source/EnhancedCodeFlow/Public/ECFSubsystem.h b/Source/EnhancedCodeFlow/Public/ECFSubsystem.h index e252066..2123883 100644 --- a/Source/EnhancedCodeFlow/Public/ECFSubsystem.h +++ b/Source/EnhancedCodeFlow/Public/ECFSubsystem.h @@ -126,6 +126,10 @@ class ENHANCEDCODEFLOW_API UECFSubsystem : public UGameInstanceSubsystem, public // Try to find running or pending action. UECFActionBase* FindAction(const FECFHandle& HandleId) const; + + // Finds the first running or pending action with the given Label and returns its FECFHandle. Returns invalid handle if not found. + FECFHandle FindActionByLabel(const FString& Label) const; + // Check if the action is running or pending to run. bool HasAction(const FECFHandle& HandleId) const; From 69b62d1b9330ff93a8f128a479fa81d993ef401e Mon Sep 17 00:00:00 2001 From: Damian Nowakowski Date: Sat, 24 Jan 2026 22:38:06 +0100 Subject: [PATCH 02/13] Add images to README for better visualization Added images to enhance documentation. --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index fa5b181..b49dd3c 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,10 @@ The plugin works on Unreal Engine: 4.27, 5.2, 5.3, 5.4, 5.5, 5.6. - [Measuring Performance](#measuring-performance) - [Logs](#logs) - [Extending Plugin](#extending-plugin) + +ecffindbyclass +ecffindbylabel + - [Special Thanks](#special-thanks) # Plugin prebuilt binaries From e30f75ed40ca0091394e007d362e4cbb28d787e0 Mon Sep 17 00:00:00 2001 From: Damian Nowakowski Date: Thu, 5 Jun 2025 14:14:04 +0200 Subject: [PATCH 03/13] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index b49dd3c..256a491 100644 --- a/README.md +++ b/README.md @@ -40,10 +40,10 @@ If you don't want to build the plugin from the source you can get the prebuilt b | UE version | Plugin version | Link | | :--------- | :------------- | :--- | | 4.27 | 3.5.3 | [Zip](https://github.com/zompi2/UE4EnhancedCodeFlow/raw/packs/Packs/EnhancedCodeFlow-3.5.3-4.27-Prebuild.zip) | -| 5.3 | 3.4.0 | [Fab](https://www.fab.com/listings/c7a13871-0671-45d5-971c-2f5b3d53d3c0) | -| 5.4 | 3.4.0 | [Fab](https://www.fab.com/listings/c7a13871-0671-45d5-971c-2f5b3d53d3c0) | -| 5.5 | 3.4.0 | [Fab](https://www.fab.com/listings/c7a13871-0671-45d5-971c-2f5b3d53d3c0) | -| 5.6 | comming soon | comming soon | +| 5.3 | 3.5.3 | [Fab](https://www.fab.com/listings/c7a13871-0671-45d5-971c-2f5b3d53d3c0) | +| 5.4 | 3.5.3 | [Fab](https://www.fab.com/listings/c7a13871-0671-45d5-971c-2f5b3d53d3c0) | +| 5.5 | 3.5.3 | [Fab](https://www.fab.com/listings/c7a13871-0671-45d5-971c-2f5b3d53d3c0) | +| 5.6 | 3.5.3 | [Fab](https://www.fab.com/listings/c7a13871-0671-45d5-971c-2f5b3d53d3c0) | [Back to top](#table-of-content) From 0e6eb9ff2af6f60c36ed8c696b84a57654343a7f Mon Sep 17 00:00:00 2001 From: Damian Nowakowski Date: Fri, 27 Jun 2025 11:59:20 +0200 Subject: [PATCH 04/13] better way of checking if coroutines are supported --- Source/EnhancedCodeFlow/Public/Coroutines/ECFCoroutine.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Source/EnhancedCodeFlow/Public/Coroutines/ECFCoroutine.h b/Source/EnhancedCodeFlow/Public/Coroutines/ECFCoroutine.h index f2f8a3e..417db11 100644 --- a/Source/EnhancedCodeFlow/Public/Coroutines/ECFCoroutine.h +++ b/Source/EnhancedCodeFlow/Public/Coroutines/ECFCoroutine.h @@ -2,7 +2,9 @@ #pragma once -#ifdef __cpp_impl_coroutine +#if defined(__cpp_impl_coroutine) && __has_include() + +#define ECF_WITH_COROUTINES 1 #include #include "ECFHandle.h" @@ -38,6 +40,8 @@ struct FECFCoroutinePromise #include "ECFHandle.h" +#define ECF_WITH_COROUTINES 0 + using FECFCoroutine = void; struct FECFCoroutinePromise From 7e16cc0ff011c7b47cdb4c771c9a22c6d5c23570 Mon Sep 17 00:00:00 2001 From: Damian Nowakowski Date: Mon, 30 Jun 2025 08:30:59 +0200 Subject: [PATCH 05/13] readme changelog and version update --- Changelog.txt | 4 ++++ EnhancedCodeFlow.uplugin | 2 +- README.md | 6 +++--- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index 812e078..ca434b4 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -1,3 +1,7 @@ +###### 3.5.4 +* Better detection of if the compiler supports coroutines or not. +* ECF_WITH_COROUTINES macro added for excluding coroutine code for compilers that do not support them. + ###### 3.5.3 * Using static delegates in timeline interp functions instead of dynamic ones diff --git a/EnhancedCodeFlow.uplugin b/EnhancedCodeFlow.uplugin index 0b79b42..6403c2d 100644 --- a/EnhancedCodeFlow.uplugin +++ b/EnhancedCodeFlow.uplugin @@ -1,7 +1,7 @@ { "FileVersion": 3, "Version": 1, - "VersionName": "3.5.3", + "VersionName": "3.5.4", "FriendlyName": "Enhanced Code Flow", "Description": "This code plugin provides functions that drastically improve the quality of life during the implementation of game flow in C++.", "Category": "Programming", diff --git a/README.md b/README.md index 256a491..dc0d7df 100644 --- a/README.md +++ b/README.md @@ -730,13 +730,13 @@ FECFHandle ActionHandle = SuspandableFunction().promise().ActionHandle; ## Checking for coroutine support -If you compile your code on multiple compilers and some of them do not support coroutines put the coroutine code into the block: +If you compile your code on multiple platforms and some of them do not support coroutines put the coroutine code into the block: ``` cpp -#ifdef __cpp_impl_coroutine +#if ECF_WITH_COROUTINES // coroutine code #endif ``` -This applies especially to places where you use coroutine keywords, like `co_awai` or `.promise()`. +This applies especially to places where you use coroutine keywords, like `co_await` or `.promise()`. [Back to coroutines](#coroutines-experimental) [Back to top](#table-of-content) From 02668a00b04cb49aa011196dd42a1835a3087055 Mon Sep 17 00:00:00 2001 From: Damian Nowakowski Date: Mon, 30 Jun 2025 08:09:00 +0200 Subject: [PATCH 06/13] Update README.md --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index dc0d7df..ea8731b 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,12 @@ If you don't want to build the plugin from the source you can get the prebuilt b [Back to top](#table-of-content) +# Other platforms support + +The plugin has been tested by me only on Windows platform, however, there should be no obstacles to use them on any other platform supported by Unreal Engine. +Thanks to @Tutul- for testing and confirming that the plugin also works on `6.12.34-1-MANJARO (based on Archlinux)` and `Android` with the default Unreal settings (however to use coroutines it requires at least `NDK r26d`). +Feel free to test the source code on any platforms you can imagine :) + # Example Project The example project wich uses this plugin can be found in **[this repository](https://github.com/zompi2/UE4EnhancedCodeFlowExample)**. Example project is compatible with the newest version of the plugin only. From 2aebccdda7c9244bfb69af30b5bab159d21f1edd Mon Sep 17 00:00:00 2001 From: Damian Nowakowski Date: Mon, 30 Jun 2025 08:10:39 +0200 Subject: [PATCH 07/13] Update README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index ea8731b..7fd814e 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ The plugin works on Unreal Engine: 4.27, 5.2, 5.3, 5.4, 5.5, 5.6. # Table of content - [Plugin prebuilt binaries](#plugin-prebuilt-binaries) +- [Other platforms support](#other-platforms-support) - [Example Project](#example-project) - [Used in...](#used-in) - [Contact](#contact) @@ -53,6 +54,8 @@ The plugin has been tested by me only on Windows platform, however, there should Thanks to @Tutul- for testing and confirming that the plugin also works on `6.12.34-1-MANJARO (based on Archlinux)` and `Android` with the default Unreal settings (however to use coroutines it requires at least `NDK r26d`). Feel free to test the source code on any platforms you can imagine :) +[Back to top](#table-of-content) + # Example Project The example project wich uses this plugin can be found in **[this repository](https://github.com/zompi2/UE4EnhancedCodeFlowExample)**. Example project is compatible with the newest version of the plugin only. From 6a1390e4417e5d229b99b5b68cb831b3293021af Mon Sep 17 00:00:00 2001 From: Damian Nowakowski Date: Mon, 30 Jun 2025 08:12:26 +0200 Subject: [PATCH 08/13] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7fd814e..aff5542 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ If you don't want to build the plugin from the source you can get the prebuilt b # Other platforms support The plugin has been tested by me only on Windows platform, however, there should be no obstacles to use them on any other platform supported by Unreal Engine. -Thanks to @Tutul- for testing and confirming that the plugin also works on `6.12.34-1-MANJARO (based on Archlinux)` and `Android` with the default Unreal settings (however to use coroutines it requires at least `NDK r26d`). +Thanks to [Tutul-](https://github.com/Tutul-) for testing and confirming that the plugin also works on `6.12.34-1-MANJARO (based on Archlinux)` and `Android` with the default Unreal settings (however to use coroutines it requires at least `NDK r26d`). Feel free to test the source code on any platforms you can imagine :) [Back to top](#table-of-content) From e2fc2471e72f3fcda367abbba13f961d8a5143eb Mon Sep 17 00:00:00 2001 From: Damian Nowakowski Date: Mon, 30 Jun 2025 08:16:52 +0200 Subject: [PATCH 09/13] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index aff5542..e15b5e8 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ If you don't want to build the plugin from the source you can get the prebuilt b # Other platforms support The plugin has been tested by me only on Windows platform, however, there should be no obstacles to use them on any other platform supported by Unreal Engine. -Thanks to [Tutul-](https://github.com/Tutul-) for testing and confirming that the plugin also works on `6.12.34-1-MANJARO (based on Archlinux)` and `Android` with the default Unreal settings (however to use coroutines it requires at least `NDK r26d`). +Thanks to [Tutul-](https://github.com/Tutul-) for testing and confirming that the plugin also works on UE5.6 on `6.12.34-1-MANJARO (based on Archlinux)` and on `Android` with the default Unreal settings (however the coroutines requires at least `NDK r26d`). Feel free to test the source code on any platforms you can imagine :) [Back to top](#table-of-content) From c5a837819da79e2002347fbd7a4c3b12b68fb535 Mon Sep 17 00:00:00 2001 From: Damian Nowakowski Date: Mon, 30 Jun 2025 08:19:29 +0200 Subject: [PATCH 10/13] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e15b5e8..42df26f 100644 --- a/README.md +++ b/README.md @@ -1019,7 +1019,7 @@ You can temporarily disable plugin's build optimizations by setting the `bDisabl # Special thanks -I want to send special thanks to Monika, because she always supports me and believes in me, to Pawel, for allowing me to test this plugin on his project and to everyone that contributed to this project. +I want to send special thanks to Monika, because she always supports me and believes in me, to Pawel, for allowing me to test this plugin on his project, to [Tutul-](https://github.com/Tutul-) for doing extensive tests on Linux and Android platforms and to everyone that contributed to this project. Also, I want to thank You for using this plugin! It is very important for me that my work is useful for someone! Happy coding! From ef16bdfa99f13d98a5e98845bdb47d0b40ed3ad5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Slagmolen=20=28Tutul=29?= Date: Fri, 4 Jul 2025 17:59:42 +0200 Subject: [PATCH 11/13] Improve tests description for Linux/LinuxArm64/Android --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 42df26f..5969f02 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,12 @@ If you don't want to build the plugin from the source you can get the prebuilt b # Other platforms support The plugin has been tested by me only on Windows platform, however, there should be no obstacles to use them on any other platform supported by Unreal Engine. -Thanks to [Tutul-](https://github.com/Tutul-) for testing and confirming that the plugin also works on UE5.6 on `6.12.34-1-MANJARO (based on Archlinux)` and on `Android` with the default Unreal settings (however the coroutines requires at least `NDK r26d`). + +Thanks to [Tutul-](https://github.com/Tutul-) for testing and confirming that the plugin also works on UE5.6 on Linux/LinuxArm64 and Android. +On Linux, the demo project was compiled on a `6.12.34-1-MANJARO` and ran on the same system. LinuxArm64 was cross-compiled and ran on an emulation of `Ubuntu-ARM` +For the `Android` target, the project work with the default Unreal recommandation for the platform target. +However, the coroutines requires at least the `NDK r26`, but the target can still follow Unreal's minimum and target API level. + Feel free to test the source code on any platforms you can imagine :) [Back to top](#table-of-content) From 73c77f7d86bcefd7023e83d4bbbd18b8c4f5bfea Mon Sep 17 00:00:00 2001 From: Damian Nowakowski Date: Fri, 5 Dec 2025 21:48:35 +0100 Subject: [PATCH 12/13] Update Unreal Engine compatibility and plugin version --- README.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 5969f02..7017147 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ This code plugin provides functions that drastically improve the quality of life during the implementation of game flow in C++. It works very well with gameplay programming, UI programming with a lot of transitions or in any other situation. -The plugin works on Unreal Engine: 4.27, 5.2, 5.3, 5.4, 5.5, 5.6. +The plugin works on Unreal Engine: 4.27, 5.2-5.7. # Table of content @@ -40,11 +40,12 @@ If you don't want to build the plugin from the source you can get the prebuilt b | UE version | Plugin version | Link | | :--------- | :------------- | :--- | -| 4.27 | 3.5.3 | [Zip](https://github.com/zompi2/UE4EnhancedCodeFlow/raw/packs/Packs/EnhancedCodeFlow-3.5.3-4.27-Prebuild.zip) | -| 5.3 | 3.5.3 | [Fab](https://www.fab.com/listings/c7a13871-0671-45d5-971c-2f5b3d53d3c0) | -| 5.4 | 3.5.3 | [Fab](https://www.fab.com/listings/c7a13871-0671-45d5-971c-2f5b3d53d3c0) | -| 5.5 | 3.5.3 | [Fab](https://www.fab.com/listings/c7a13871-0671-45d5-971c-2f5b3d53d3c0) | -| 5.6 | 3.5.3 | [Fab](https://www.fab.com/listings/c7a13871-0671-45d5-971c-2f5b3d53d3c0) | +| 4.27 | 3.5.4 | [Zip](https://github.com/zompi2/UE4EnhancedCodeFlow/raw/packs/Packs/EnhancedCodeFlow-3.5.4-4.27-Prebuild.zip) | +| 5.3 | 3.5.4 | [Fab](https://www.fab.com/listings/c7a13871-0671-45d5-971c-2f5b3d53d3c0) | +| 5.4 | 3.5.4 | [Fab](https://www.fab.com/listings/c7a13871-0671-45d5-971c-2f5b3d53d3c0) | +| 5.5 | 3.5.4 | [Fab](https://www.fab.com/listings/c7a13871-0671-45d5-971c-2f5b3d53d3c0) | +| 5.6 | 3.5.4 | [Fab](https://www.fab.com/listings/c7a13871-0671-45d5-971c-2f5b3d53d3c0) | +| 5.7 | 3.5.4 | [Fab](https://www.fab.com/listings/c7a13871-0671-45d5-971c-2f5b3d53d3c0) | [Back to top](#table-of-content) From e42e90084798547e4f7f849cd59134e1cefff74c Mon Sep 17 00:00:00 2001 From: Damian Nowakowski Date: Sat, 24 Jan 2026 23:07:54 +0100 Subject: [PATCH 13/13] Finishing labels functionality and adding more functions for control --- Changelog.txt | 8 +++ EnhancedCodeFlow.uplugin | 2 +- README.md | 27 ++++++-- .../Private/BP/ECFBPLibrary.cpp | 30 +++++++-- .../EnhancedCodeFlow/Private/ECFSubsystem.cpp | 63 +++++++++++++++---- .../Private/EnhancedCodeFlow.cpp | 49 ++++++++++++--- .../EnhancedCodeFlow/Public/BP/ECFBPLibrary.h | 18 ++++-- .../EnhancedCodeFlow/Public/ECFActionBase.h | 26 +++++--- .../Public/ECFActionSettings.h | 1 + Source/EnhancedCodeFlow/Public/ECFSubsystem.h | 24 ++++--- .../Public/EnhancedCodeFlow.h | 38 +++++++++++ 11 files changed, 236 insertions(+), 50 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index ca434b4..5e719ab 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -1,3 +1,11 @@ +###### 3.6.0 +* Added Labels. You can add a Label to every Action which helps with debugging (Labels are displayed in logs) and you + can search for running action's handles by these Labels. +* GetActionsHandlesByClass and GetActionsHandlesByLabel functions added which returns an array of handles of valid Actions. +* GetAllActions, GetActionsCount, GetActionFromHandle, and GetActionFromInstancedId functions has been added for C++, which + returns pointers to actual Actions objects. Use them for DEBUGGING purposes only! +* MarkAsFinished function is now protected + ###### 3.5.4 * Better detection of if the compiler supports coroutines or not. * ECF_WITH_COROUTINES macro added for excluding coroutine code for compilers that do not support them. diff --git a/EnhancedCodeFlow.uplugin b/EnhancedCodeFlow.uplugin index 6403c2d..10bac43 100644 --- a/EnhancedCodeFlow.uplugin +++ b/EnhancedCodeFlow.uplugin @@ -1,7 +1,7 @@ { "FileVersion": 3, "Version": 1, - "VersionName": "3.5.4", + "VersionName": "3.6.0", "FriendlyName": "Enhanced Code Flow", "Description": "This code plugin provides functions that drastically improve the quality of life during the implementation of game flow in C++.", "Category": "Programming", diff --git a/README.md b/README.md index 7017147..a4f10f0 100644 --- a/README.md +++ b/README.md @@ -22,16 +22,13 @@ The plugin works on Unreal Engine: 4.27, 5.2-5.7. - [Extra Settings](#extra-settings) - [Instanced Actions](#instanced-actions) - [Coroutines (experimental)](#coroutines-experimental) +- [Getting Running Actions](#getting-running-actions) - [Pausing and Resuming](#pausing-and-resuming) - [Stopping Actions](#stopping-actions) - [Resetting Actions](#resetting-actions) - [Measuring Performance](#measuring-performance) - [Logs](#logs) - [Extending Plugin](#extending-plugin) - -ecffindbyclass -ecffindbylabel - - [Special Thanks](#special-thanks) # Plugin prebuilt binaries @@ -573,6 +570,7 @@ You can define extra settings at the end of each action launch. Currently the fo * Ignore Game Pause - it will ignore the game pause. * Ignore Global Time Dilation - it will ignore global time dilation when ticking. * Start Paused - the action will start in paused state and must be resumed manually. +* Label - the string that can be used to identify the action. ``` cpp FFlow::AddTicker(this, 10.f, [this](float DeltaTime) @@ -756,6 +754,27 @@ This applies especially to places where you use coroutine keywords, like `co_awa [Back to coroutines](#coroutines-experimental) [Back to top](#table-of-content) +# Getting Running Actions +To get running action's handles use one of the following functions: + +#### Get Actions Handles by Class + +```cpp +TArray Handles = FFlow::GetActionsHandlesByClass(GetWorld()); +``` + +ecffindbyclass + +#### Get Actions Handles by Label + +```cpp +TArray Handles = FFlow::GetActionsHandlesByLabel(TEXT("MyLabel")); +``` + +ecffindbylabel + +[Back to top](#table-of-content) + # Pausing and Resuming ## Actions diff --git a/Source/EnhancedCodeFlow/Private/BP/ECFBPLibrary.cpp b/Source/EnhancedCodeFlow/Private/BP/ECFBPLibrary.cpp index 5ef7544..2e7909b 100644 --- a/Source/EnhancedCodeFlow/Private/BP/ECFBPLibrary.cpp +++ b/Source/EnhancedCodeFlow/Private/BP/ECFBPLibrary.cpp @@ -24,6 +24,30 @@ void UECFBPLibrary::ECFIsActionRunning(bool& bIsRunning, const UObject* WorldCon bIsRunning = FFlow::IsActionRunning(WorldContextObject, Handle.Handle); } +TArray UECFBPLibrary::GetActionsHandlesByClass(const UObject* WorldContextObject, TSubclassOf Class) +{ + TArray Result = FFlow::GetActionsHandlesByClass(WorldContextObject, Class); + TArray ResultBP; + ResultBP.Reserve(Result.Num()); + for (const FECFHandle& Handle : Result) + { + ResultBP.Add(FECFHandleBP(Handle)); + } + return ResultBP; +} + +TArray UECFBPLibrary::GetActionsHandlesByLabel(const UObject* WorldContextObject, const FString& Label) +{ + TArray Result = FFlow::GetActionsHandlesByLabel(WorldContextObject, Label); + TArray ResultBP; + ResultBP.Reserve(Result.Num()); + for (const FECFHandle& Handle : Result) + { + ResultBP.Add(FECFHandleBP(Handle)); + } + return ResultBP; +} + void UECFBPLibrary::ECFPauseAction(const UObject* WorldContextObject, const FECFHandleBP& Handle) { FFlow::PauseAction(WorldContextObject, Handle.Handle); @@ -182,11 +206,5 @@ FString UECFBPLibrary::Conv_ECFInstanceIdToString(const FECFInstanceIdBP& Instan return InstanceId.InstanceId.ToString(); } -/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ - -FECFHandleBP UECFBPLibrary::FindActionByLabel(const UObject* WorldContextObject, const FString& Label) -{ - return FECFHandleBP(FFlow::FindActionByLabel(WorldContextObject, Label)); -} ECF_PRAGMA_ENABLE_OPTIMIZATION \ No newline at end of file diff --git a/Source/EnhancedCodeFlow/Private/ECFSubsystem.cpp b/Source/EnhancedCodeFlow/Private/ECFSubsystem.cpp index abb1915..e5cf3ee 100644 --- a/Source/EnhancedCodeFlow/Private/ECFSubsystem.cpp +++ b/Source/EnhancedCodeFlow/Private/ECFSubsystem.cpp @@ -138,29 +138,70 @@ UECFActionBase* UECFSubsystem::FindAction(const FECFHandle& HandleId) const return nullptr; } -FECFHandle UECFSubsystem::FindActionByLabel(const FString& Label) const +TArray UECFSubsystem::GetActionsHandlesByClass(TSubclassOf Class) const { + TArray Result; + if (Class == nullptr) + { + return Result; + } + // Search in active actions + for (UECFActionBase* Action : Actions) + { + if (IsActionValid(Action) && (Action->GetClass() == Class)) + { + Result.Add(Action->GetHandleId()); + } + } + // Search in pending actions + for (UECFActionBase* PendingAction : PendingAddActions) + { + if (IsActionValid(PendingAction) && (PendingAction->GetClass() == Class)) + { + Result.Add(PendingAction->GetHandleId()); + } + } + return Result; +} + +TArray UECFSubsystem::GetActionsHandlesByLabel(const FString& Label) const +{ + TArray Result; if (Label.IsEmpty()) { - return FECFHandle(); + return Result; } // Search in active actions for (UECFActionBase* Action : Actions) { - if (IsActionValid(Action) && Action->Settings.Label == Label) + if (IsActionValid(Action) && (Action->Settings.Label == Label)) { - return Action->GetHandleId(); + Result.Add(Action->GetHandleId()); } } // Search in pending actions for (UECFActionBase* PendingAction : PendingAddActions) { - if (IsActionValid(PendingAction) && PendingAction->Settings.Label == Label) + if (IsActionValid(PendingAction) && (PendingAction->Settings.Label == Label)) { - return PendingAction->GetHandleId(); + Result.Add(PendingAction->GetHandleId()); } } - return FECFHandle(); + return Result; +} + +TArray UECFSubsystem::GetAllActions() const +{ + TArray Result; + Result.Reserve(GetActionsCount()); + Result.Append(Actions); + Result.Append(PendingAddActions); + return Result; +} + +int32 UECFSubsystem::GetActionsCount() const +{ + return Actions.Num() + PendingAddActions.Num(); } void UECFSubsystem::PauseAction(const FECFHandle& HandleId) @@ -168,7 +209,7 @@ void UECFSubsystem::PauseAction(const FECFHandle& HandleId) if (UECFActionBase* ActionFound = FindAction(HandleId)) { #if (ECF_LOGS && ECF_LOGS_VERBOSE) - UE_LOG(LogECF, Verbose, TEXT("Paused Action of class: %s"), *ActionFound->GetName()); + UE_LOG(LogECF, Verbose, TEXT("Paused Action of class: %s, Label: %s"), *ActionFound->GetName(), *ActionFound->GetLabel()); #endif ActionFound->bIsPaused = true; } @@ -185,7 +226,7 @@ void UECFSubsystem::ResumeAction(const FECFHandle& HandleId) if (UECFActionBase* ActionFound = FindAction(HandleId)) { #if (ECF_LOGS && ECF_LOGS_VERBOSE) - UE_LOG(LogECF, Verbose, TEXT("Resume Action of class: %s"), *ActionFound->GetName()); + UE_LOG(LogECF, Verbose, TEXT("Resume Action of class: %s, Label: %s"), *ActionFound->GetName(), *ActionFound->GetLabel()); #endif ActionFound->bIsPaused = false; } @@ -214,7 +255,7 @@ void UECFSubsystem::ResetAction(const FECFHandle& HandleId, bool bCallUpdate) if (IsActionValid(ActionFound)) { #if (ECF_LOGS && ECF_LOGS_VERBOSE) - UE_LOG(LogECF, Verbose, TEXT("Reset Action of class: %s"), *ActionFound->GetName()); + UE_LOG(LogECF, Verbose, TEXT("Reset Action of class: %s, Label: %s"), *ActionFound->GetName(), *ActionFound->GetLabel()); #endif ActionFound->Reset(bCallUpdate); return; @@ -231,7 +272,7 @@ void UECFSubsystem::RemoveAction(FECFHandle& HandleId, bool bComplete) if (UECFActionBase* ActionFound = FindAction(HandleId)) { #if (ECF_LOGS && ECF_LOGS_VERBOSE) - UE_LOG(LogECF, Verbose, TEXT("Remove Action of class: %s"), *ActionFound->GetName()); + UE_LOG(LogECF, Verbose, TEXT("Remove Action of class: %s, Label: %s"), *ActionFound->GetName(), *ActionFound->GetLabel()); #endif FinishAction(ActionFound, bComplete); HandleId.Invalidate(); diff --git a/Source/EnhancedCodeFlow/Private/EnhancedCodeFlow.cpp b/Source/EnhancedCodeFlow/Private/EnhancedCodeFlow.cpp index e97cad9..e3fff6c 100644 --- a/Source/EnhancedCodeFlow/Private/EnhancedCodeFlow.cpp +++ b/Source/EnhancedCodeFlow/Private/EnhancedCodeFlow.cpp @@ -37,6 +37,48 @@ bool FFlow::IsActionRunning(const UObject* WorldContextObject, const FECFHandle& return false; } +TArray FEnhancedCodeFlow::GetActionsHandlesByClass(const UObject* WorldContextObject, TSubclassOf Class) +{ + if (UECFSubsystem* ECF = UECFSubsystem::Get(WorldContextObject)) + return ECF->GetActionsHandlesByClass(Class); + return {}; +} + +TArray FEnhancedCodeFlow::GetActionsHandlesByLabel(const UObject* WorldContextObject, const FString& Label) +{ + if (UECFSubsystem* ECF = UECFSubsystem::Get(WorldContextObject)) + return ECF->GetActionsHandlesByLabel(Label); + return {}; +} + +TArray FEnhancedCodeFlow::GetAllActions(const UObject* WorldContextObject) +{ + if (UECFSubsystem* ECF = UECFSubsystem::Get(WorldContextObject)) + return ECF->GetAllActions(); + return {}; +} + +int32 FEnhancedCodeFlow::GetActionsCount(const UObject* WorldContextObject) +{ + if (UECFSubsystem* ECF = UECFSubsystem::Get(WorldContextObject)) + return ECF->GetActionsCount(); + return 0; +} + +UECFActionBase* FEnhancedCodeFlow::GetActionFromHandle(const UObject* WorldContextObject, const FECFHandle& Handle) +{ + if (UECFSubsystem* ECF = UECFSubsystem::Get(WorldContextObject)) + return ECF->FindAction(Handle); + return nullptr; +} + +UECFActionBase* FEnhancedCodeFlow::GetActionFromHandle(const UObject* WorldContextObject, const FECFInstanceId& InstancedId) +{ + if (UECFSubsystem* ECF = UECFSubsystem::Get(WorldContextObject)) + return ECF->GetInstancedAction(InstancedId); + return nullptr; +} + void FEnhancedCodeFlow::PauseAction(const UObject* WorldContextObject, const FECFHandle& Handle) { if (UECFSubsystem* ECF = UECFSubsystem::Get(WorldContextObject)) @@ -589,11 +631,4 @@ void FEnhancedCodeFlow::RemoveAllRunAsyncAndWait(const UObject* WorldContextObje ECF->RemoveActionsOfClass(bComplete, InOwner); } -FECFHandle FEnhancedCodeFlow::FindActionByLabel(const UObject* WorldContextObject, const FString& Label) -{ - if (UECFSubsystem* ECF = UECFSubsystem::Get(WorldContextObject)) - return ECF->FindActionByLabel(Label); - return FECFHandle(); -} - ECF_PRAGMA_ENABLE_OPTIMIZATION diff --git a/Source/EnhancedCodeFlow/Public/BP/ECFBPLibrary.h b/Source/EnhancedCodeFlow/Public/BP/ECFBPLibrary.h index 7d13b15..fabd5cf 100644 --- a/Source/EnhancedCodeFlow/Public/BP/ECFBPLibrary.h +++ b/Source/EnhancedCodeFlow/Public/BP/ECFBPLibrary.h @@ -47,6 +47,18 @@ class ENHANCEDCODEFLOW_API UECFBPLibrary : public UBlueprintFunctionLibrary UFUNCTION(BlueprintPure, meta = (WorldContext = "WorldContextObject", DisplayName = "ECF - Is Action Running"), Category = "ECF") static void ECFIsActionRunning(UPARAM(DisplayName = "IsRunning") bool& bIsRunning, const UObject* WorldContextObject, const FECFHandleBP& Handle); + /** + * Finds handles of running or pending action of the given Class its FECFHandles. + */ + UFUNCTION(BlueprintPure, meta = (WorldContext = "WorldContextObject", DisplayName = "ECF - Get Actions Handles By Class"), Category = "ECF") + static TArray GetActionsHandlesByClass(const UObject* WorldContextObject, TSubclassOf Class); + + /** + * Finds handles of running or pending action of the given Label its FECFHandles (for Blueprints). + */ + UFUNCTION(BlueprintPure, meta = (WorldContext = "WorldContextObject", DisplayName = "ECF - Get Actions Handles By Label"), Category = "ECF") + static TArray GetActionsHandlesByLabel(const UObject* WorldContextObject, const FString& Label); + /** * Pause running action. */ @@ -261,11 +273,5 @@ class ENHANCEDCODEFLOW_API UECFBPLibrary : public UBlueprintFunctionLibrary UFUNCTION(BlueprintPure, meta = (DisplayName = "ToString (FECFInstanceIdBP)", CompactNodeTitle = "->", BlueprintAutocast), Category = "ECF") static FString Conv_ECFInstanceIdToString(const FECFInstanceIdBP& InstanceId); - /** - * Finds the first running or pending action with the given Label and returns its handle (for Blueprints). - */ - UFUNCTION(BlueprintPure, meta = (WorldContext = "WorldContextObject", DisplayName = "ECF - Find Action By Label"), Category = "ECF") - static FECFHandleBP FindActionByLabel(const UObject* WorldContextObject, const FString& Label); - /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ }; diff --git a/Source/EnhancedCodeFlow/Public/ECFActionBase.h b/Source/EnhancedCodeFlow/Public/ECFActionBase.h index b675788..b6f1d38 100644 --- a/Source/EnhancedCodeFlow/Public/ECFActionBase.h +++ b/Source/EnhancedCodeFlow/Public/ECFActionBase.h @@ -54,14 +54,16 @@ class ENHANCEDCODEFLOW_API UECFActionBase : public UObject return InstanceId; } - // Marks this action as finished. It makes it invalid. - // This action will be deleted soon. - void MarkAsFinished() + // Returns this action Label + FString GetLabel() const { -#if (ECF_LOGS && ECF_LOGS_VERBOSE) - UE_LOG(LogECF, Verbose, TEXT("Action of class %s marked as finished"), *GetName()); -#endif - bHasFinished = true; + return Settings.Label; + } + + // Checks if this action is paused + bool IsPaused() const + { + return bIsPaused; } // Checks if this action has this instance id. @@ -93,6 +95,16 @@ class ENHANCEDCODEFLOW_API UECFActionBase : public UObject // Function called when the action is requested to be completed before it ends. virtual void Complete(bool bStopped) {} + // Marks this action as finished. It makes it invalid. + // This action will be deleted soon. + void MarkAsFinished() + { +#if (ECF_LOGS && ECF_LOGS_VERBOSE) + UE_LOG(LogECF, Verbose, TEXT("Action of class %s marked as finished, Label: %s"), *GetName(), *GetLabel()); +#endif + bHasFinished = true; + } + // Function called when this action is instanced and something tried to call it again. virtual void RetriggeredInstancedAction() {} diff --git a/Source/EnhancedCodeFlow/Public/ECFActionSettings.h b/Source/EnhancedCodeFlow/Public/ECFActionSettings.h index 071319f..40cdccc 100644 --- a/Source/EnhancedCodeFlow/Public/ECFActionSettings.h +++ b/Source/EnhancedCodeFlow/Public/ECFActionSettings.h @@ -56,3 +56,4 @@ struct ENHANCEDCODEFLOW_API FECFActionSettings #define ECF_IGNORETIMEDILATION FECFActionSettings(0.f, 0.f, false, true, false, TEXT("")) #define ECF_IGNOREPAUSEDILATION FECFActionSettings(0.f, 0.f, true, true, false, TEXT("")) #define ECF_STARTPAUSED FECFActionSettings(0.f, 0.f, false, false, true, TEXT("")) +#define ECF_LABEL(_Label) FECFActionSettings(0.f, 0.f, false, false, false, _Label) diff --git a/Source/EnhancedCodeFlow/Public/ECFSubsystem.h b/Source/EnhancedCodeFlow/Public/ECFSubsystem.h index 2123883..1b7beb5 100644 --- a/Source/EnhancedCodeFlow/Public/ECFSubsystem.h +++ b/Source/EnhancedCodeFlow/Public/ECFSubsystem.h @@ -70,11 +70,11 @@ class ENHANCEDCODEFLOW_API UECFSubsystem : public UGameInstanceSubsystem, public #if (ECF_LOGS && ECF_LOGS_VERBOSE) if (InstanceId.IsValid()) { - UE_LOG(LogECF, Verbose, TEXT("Started Instanced Action of class: %s, with HandleId: %s, and InstanceId: %s"), *NewAction->GetName(), *LastHandleId.ToString(), *InstanceId.ToString()); + UE_LOG(LogECF, Verbose, TEXT("Started Instanced Action of class: %s, with HandleId: %s, and InstanceId: %s, Label: %s"), *NewAction->GetName(), *LastHandleId.ToString(), *InstanceId.ToString(), *Settings.Label); } else { - UE_LOG(LogECF, Verbose, TEXT("Started Action of class: %s, with HandleId: %s"), *NewAction->GetName(), *LastHandleId.ToString()); + UE_LOG(LogECF, Verbose, TEXT("Started Action of class: %s, with HandleId: %s, Label: %s"), *NewAction->GetName(), *LastHandleId.ToString(), *Settings.Label); } #endif return NewAction->GetHandleId(); @@ -82,7 +82,7 @@ class ENHANCEDCODEFLOW_API UECFSubsystem : public UGameInstanceSubsystem, public else { #if ECF_LOGS - UE_LOG(LogECF, Error, TEXT("Failed to Setup Action of class: %s"), *NewAction->GetName()); + UE_LOG(LogECF, Error, TEXT("Failed to Setup Action of class: %s, Label: %s"), *NewAction->GetName(), *Settings.Label); #endif } @@ -111,24 +111,32 @@ class ENHANCEDCODEFLOW_API UECFSubsystem : public UGameInstanceSubsystem, public { NewAction->Init(); #if (ECF_LOGS && ECF_LOGS_VERBOSE) - UE_LOG(LogECF, Verbose, TEXT("Started Coroutine Action of class: %s"), *NewAction->GetName()); + UE_LOG(LogECF, Verbose, TEXT("Started Coroutine Action of class: %s, Label: %s"), *NewAction->GetName(), *Settings.Label); #endif PendingAddActions.Add(NewAction); } else { #if ECF_LOGS - UE_LOG(LogECF, Error, TEXT("Failed to Setup Coroutine Action of class: %s"), *NewAction->GetName()); + UE_LOG(LogECF, Error, TEXT("Failed to Setup Coroutine Action of class: %s, Label: %s"), *NewAction->GetName(), *Settings.Label); #endif } } - // Try to find running or pending action. + // Try to find running or pending action based on it's handle. UECFActionBase* FindAction(const FECFHandle& HandleId) const; + // Finds handles of running or pending action of the given Class its FECFHandles. + TArray GetActionsHandlesByClass(TSubclassOf Class) const; - // Finds the first running or pending action with the given Label and returns its FECFHandle. Returns invalid handle if not found. - FECFHandle FindActionByLabel(const FString& Label) const; + // Finds handles of running or pending action of the given Label its FECFHandles. + TArray GetActionsHandlesByLabel(const FString& Label) const; + + // Returns the array of all running and pending actions. Use it mostly for debugging purposes. + TArray GetAllActions() const; + + // Returns the number of all running and pending actions. Use it mostly for debugging purposes. + int32 GetActionsCount() const; // Check if the action is running or pending to run. bool HasAction(const FECFHandle& HandleId) const; diff --git a/Source/EnhancedCodeFlow/Public/EnhancedCodeFlow.h b/Source/EnhancedCodeFlow/Public/EnhancedCodeFlow.h index fb08a33..46907fc 100644 --- a/Source/EnhancedCodeFlow/Public/EnhancedCodeFlow.h +++ b/Source/EnhancedCodeFlow/Public/EnhancedCodeFlow.h @@ -45,6 +45,42 @@ class ENHANCEDCODEFLOW_API FEnhancedCodeFlow */ static bool IsActionRunning(const UObject* WorldContextObject, const FECFHandle& Handle); + /** + * Finds handles of running or pending action of the given Class its FECFHandles. + */ + static TArray GetActionsHandlesByClass(const UObject* WorldContextObject, TSubclassOf Class); + + template + static TArray GetActionsHandlesByClass(const UObject* WorldContextObject) + { + return GetActionsHandlesByClass(WorldContextObject, T::StaticClass()); + } + + /** + * Finds handles of running or pending action of the given Label its FECFHandles. + */ + static TArray GetActionsHandlesByLabel(const UObject* WorldContextObject, const FString& Label); + + /** + * Returns the array of all running and pending actions. Use it mostly for debugging purposes. + */ + static TArray GetAllActions(const UObject* WorldContextObject); + + /** + * Returns the number of all running and pending actions. Use it mostly for debugging purposes. + */ + static int32 GetActionsCount(const UObject* WorldContextObject); + + /** + * Returns the popinter to the Action. Use it mostly for debugging purposes. + */ + static UECFActionBase* GetActionFromHandle(const UObject* WorldContextObject, const FECFHandle& Handle); + + /** + * Returns the popinter to the Instanced Action. Use it mostly for debugging purposes. + */ + static UECFActionBase* GetActionFromHandle(const UObject* WorldContextObject, const FECFInstanceId& InstancedId); + /** * Pause ticking in the action pointed by given handle. */ @@ -533,6 +569,8 @@ class ENHANCEDCODEFLOW_API FEnhancedCodeFlow * it will remove Wait Until actions from everywhere. */ static void RemoveAllRunAsyncAndWait(const UObject* WorldContextObject, bool bComplete = false, UObject* InOwner = nullptr); + + }; using FFlow = FEnhancedCodeFlow; \ No newline at end of file