Last active
October 8, 2023 04:06
-
-
Save lordliquid/b090369372fdb6912462f3292ace5f16 to your computer and use it in GitHub Desktop.
RunOnce Delegate in Unreal Engine
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "CoreMinimal.h" | |
class FRunOnce | |
{ | |
public: | |
FORCEINLINE FRunOnce() : bHasRan(false) {} | |
FORCEINLINE explicit FRunOnce(const bool bStartClosed) : bHasRan(bStartClosed) {} | |
FORCEINLINE bool Execute() { return bHasRan ? false : bHasRan = true; } | |
FORCEINLINE void Reset() { bHasRan = false; } | |
private: | |
bool bHasRan; | |
}; | |
template <typename... T> | |
class TRunOnce : TDelegate<void(T...)> | |
{ | |
public: | |
FORCEINLINE TRunOnce() : RunOnce(MakeShared<FRunOnce>(false)) {} | |
FORCEINLINE explicit TRunOnce(const bool bStartClosed) : RunOnce(MakeShared<FRunOnce>(bStartClosed)) {} | |
FORCEINLINE bool ExecuteOnce(T... Args) | |
{ | |
return RunOnce->Execute() ? TDelegate<void(T...)>::ExecuteIfBound(Args...) : false; | |
} | |
FORCEINLINE void Reset() | |
{ | |
RunOnce->Reset(); | |
} | |
template<typename FunctorType, typename... VarTypes> | |
FORCEINLINE void BindLambda(FunctorType&& Functor, VarTypes&&... Vars) | |
{ | |
TDelegate<void(T...)>::BindLambda(MoveTemp(Functor), MoveTemp(Vars)...); | |
} | |
private: | |
TSharedPtr<FRunOnce> RunOnce; | |
}; | |
class FSandboxUtilitiesModule : public IModuleInterface | |
{ | |
public: | |
/** IModuleInterface implementation */ | |
virtual void StartupModule() override; | |
virtual void ShutdownModule() override; | |
private: | |
TSharedPtr<TRunOnce<FString>> RunOnceDelegate; | |
}; | |
void FSandboxUtilitiesModule::StartupModule() | |
{ | |
RunOnceDelegate = MakeShared<TRunOnce<FString>>(); | |
RunOnceDelegate->BindLambda([] (const FString& Message) | |
{ | |
UE_LOG(LogTemp, Warning, TEXT("Hello from SandboxUtilitiesModule: %s"), *Message); | |
}); | |
// Should only run twice total, one for each loop before and after reset. | |
for (int i = 0; i < 10; ++i) | |
{ | |
RunOnceDelegate->ExecuteOnce(FString(TEXT("Testing RunOnceDelegate"))); | |
} | |
RunOnceDelegate->Reset(); | |
for (int i = 0; i < 10; ++i) | |
{ | |
RunOnceDelegate->ExecuteOnce(FString(TEXT("Testing RunOnceDelegate"))); | |
} | |
} | |
void FSandboxUtilitiesModule::ShutdownModule() | |
{ | |
// This function may be called during shutdown to clean up your module. For modules that support dynamic reloading, | |
// we call this function before unloading the module. | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment