Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions Changelog.txt
Original file line number Diff line number Diff line change
@@ -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.
Expand Down
2 changes: 1 addition & 1 deletion EnhancedCodeFlow.uplugin
Original file line number Diff line number Diff line change
@@ -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",
Expand Down
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ 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)
Expand Down Expand Up @@ -569,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)
Expand Down Expand Up @@ -752,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<FECFHandle> Handles = FFlow::GetActionsHandlesByClass<UECFDelay>(GetWorld());
```

<img width="335" height="121" alt="ecffindbyclass" src="https://github.com/user-attachments/assets/c0ed2205-8f6a-4c15-9282-3f21938d0af6" />

#### Get Actions Handles by Label

```cpp
TArray<FECFHandle> Handles = FFlow::GetActionsHandlesByLabel<UECFDelay>(TEXT("MyLabel"));
```

<img width="313" height="94" alt="ecffindbylabel" src="https://github.com/user-attachments/assets/5982c741-a064-4e02-a02b-72caa64f49cb" />

[Back to top](#table-of-content)

# Pausing and Resuming
## Actions

Expand Down
25 changes: 24 additions & 1 deletion Source/EnhancedCodeFlow/Private/BP/ECFBPLibrary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,30 @@ void UECFBPLibrary::ECFIsActionRunning(bool& bIsRunning, const UObject* WorldCon
bIsRunning = FFlow::IsActionRunning(WorldContextObject, Handle.Handle);
}

TArray<FECFHandleBP> UECFBPLibrary::GetActionsHandlesByClass(const UObject* WorldContextObject, TSubclassOf<UECFActionBase> Class)
{
TArray<FECFHandle> Result = FFlow::GetActionsHandlesByClass(WorldContextObject, Class);
TArray<FECFHandleBP> ResultBP;
ResultBP.Reserve(Result.Num());
for (const FECFHandle& Handle : Result)
{
ResultBP.Add(FECFHandleBP(Handle));
}
return ResultBP;
}

TArray<FECFHandleBP> UECFBPLibrary::GetActionsHandlesByLabel(const UObject* WorldContextObject, const FString& Label)
{
TArray<FECFHandle> Result = FFlow::GetActionsHandlesByLabel(WorldContextObject, Label);
TArray<FECFHandleBP> 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);
Expand Down Expand Up @@ -182,6 +206,5 @@ FString UECFBPLibrary::Conv_ECFInstanceIdToString(const FECFInstanceIdBP& Instan
return InstanceId.InstanceId.ToString();
}

/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/

ECF_PRAGMA_ENABLE_OPTIMIZATION
74 changes: 70 additions & 4 deletions Source/EnhancedCodeFlow/Private/ECFSubsystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,12 +138,78 @@ UECFActionBase* UECFSubsystem::FindAction(const FECFHandle& HandleId) const
return nullptr;
}

TArray<FECFHandle> UECFSubsystem::GetActionsHandlesByClass(TSubclassOf<UECFActionBase> Class) const
{
TArray<FECFHandle> 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<FECFHandle> UECFSubsystem::GetActionsHandlesByLabel(const FString& Label) const
{
TArray<FECFHandle> Result;
if (Label.IsEmpty())
{
return Result;
}
// Search in active actions
for (UECFActionBase* Action : Actions)
{
if (IsActionValid(Action) && (Action->Settings.Label == Label))
{
Result.Add(Action->GetHandleId());
}
}
// Search in pending actions
for (UECFActionBase* PendingAction : PendingAddActions)
{
if (IsActionValid(PendingAction) && (PendingAction->Settings.Label == Label))
{
Result.Add(PendingAction->GetHandleId());
}
}
return Result;
}

TArray<UECFActionBase*> UECFSubsystem::GetAllActions() const
{
TArray<UECFActionBase*> 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)
{
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;
}
Expand All @@ -160,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;
}
Expand Down Expand Up @@ -189,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;
Expand All @@ -206,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();
Expand Down
42 changes: 42 additions & 0 deletions Source/EnhancedCodeFlow/Private/EnhancedCodeFlow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,48 @@ bool FFlow::IsActionRunning(const UObject* WorldContextObject, const FECFHandle&
return false;
}

TArray<FECFHandle> FEnhancedCodeFlow::GetActionsHandlesByClass(const UObject* WorldContextObject, TSubclassOf<UECFActionBase> Class)
{
if (UECFSubsystem* ECF = UECFSubsystem::Get(WorldContextObject))
return ECF->GetActionsHandlesByClass(Class);
return {};
}

TArray<FECFHandle> FEnhancedCodeFlow::GetActionsHandlesByLabel(const UObject* WorldContextObject, const FString& Label)
{
if (UECFSubsystem* ECF = UECFSubsystem::Get(WorldContextObject))
return ECF->GetActionsHandlesByLabel(Label);
return {};
}

TArray<UECFActionBase*> 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))
Expand Down
12 changes: 12 additions & 0 deletions Source/EnhancedCodeFlow/Public/BP/ECFBPLibrary.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<FECFHandleBP> GetActionsHandlesByClass(const UObject* WorldContextObject, TSubclassOf<UECFActionBase> 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<FECFHandleBP> GetActionsHandlesByLabel(const UObject* WorldContextObject, const FString& Label);

/**
* Pause running action.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
4 changes: 2 additions & 2 deletions Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFDelay.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
2 changes: 1 addition & 1 deletion Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFDoOnce.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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;
}
Expand All @@ -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;
}
Expand Down
2 changes: 1 addition & 1 deletion Source/EnhancedCodeFlow/Public/CodeFlowActions/ECFTicker.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
Loading