I used an enum class ref and ExpandEnumAsExecs.
UENUM(BlueprintType)
enum class OUT_EXEC : uint8
{
Completed,
Interrupted
};
Your latent function could look like:
UFUNCTION(BlueprintCallable, Category="MyCategory", meta=(ExpandEnumAsExecs="exec", Latent, WorldContext="WorldContextObject", LatentInfo="LatentInfo", interupt="false"))
void Generate_async(UObject* WorldContextObject, UPARAM(ref) bool interrupt, AActor* Some_actor, OUT_EXEC& exec, struct FLatentActionInfo LatentInfo);
then you would pass interrupt and exec reference as well as Some_actor pointer down to your subclass of FPendingLatentAction
. Your UpdateOperation(FLatentResponse& Response)
implementation could look something like this:
virtual void UpdateOperation(FLatentResponse& Response) override
{
// Do stuff with Some_actor. Maybe an iteration that takes a long time.
Some_actor->DoWork(iter++);
bool finish_flag = Some_actor->WorkIsCompleted();
if (finish_flag)
{
exec = OUT_EXEC::Completed;
}
else if (interrupt) // don't run this if finish_flag is already true
{
Some_actor->CancelWork();
exec = OUT_EXEC::Interrupted;
}
Response.FinishAndTriggerIf(finish_flag || interrupt, ExecutionFunction, OutputLink, CallbackTarget);
}
Now when you want to interrupt this, you just need to set the bool variable that you passed in as a reference to true. A down side of this is that you can only call latent nodes from an event graph so you either have a bunch of boolean variables in your blueprint or you can wrap all this up in a separate object that can be created and disposed of when it’s all done.
Here is an image to help me explain how it works.
That Generate Async node is a latent node that I created using what I explained above. This particular node will pass information off to a thread pool if the pool is not too full. If it is too full it sets my OUT_EXEC exec
to Failed and triggers the response, otherwise it adds the work to the pool and when the work is completed sets the OUT_EXEC exec
to Success and triggers the response. As a result, the appropriate output exec pin gets called.