Waiting for an event in a function/macro (inverting the inversion of control)

I am trying to figure out the best way to perform sequential calls to an asynchronous API in Blueprints, without getting the call sequence scattered all over the place in separate event handlers.

Everything seems clear and straightforward as long as I am working in a base level Blueprint graph (like the default EventGraph). For example, opening a media asset, waiting for it to open and then pausing on the first frame is easy to do like this:

However, I don’t know how to use such continuations in a reusable context: neither functions nor macros accept any event-related nodes like binding, handling or unbinding (I completely understand the reason for functions not allowing these, but I’m not sure whether there is any fundamental reason for not having these in a macro…).

I have so far just side-stepped this with an ugly hack (taken from somewhere inside the Safe Pause node in the preceding example):

…where the Can Receive Command? node polls on a flag that is set by a global event handler.

Needless to say, this approach quickly results in a mess. I just stumbled on this again while trying to create a macro/function that obtains the duration of a media asset. The needed steps are simple:

  1. Open the media asset
  2. Wait until the open operation has completed (completion is signalled via the Media Player’s On Media Opened delegate)
  3. Read the duration
  4. Close the media asset
  5. Return the duration

I would really like to not create yet more global state and/or polling to deal with this but instead figure out (partly also out of curiosity) a proper way to do it. So, is there any reasonable way to obtain such reinversion of control in Blueprints at the moment, without having to do it all in global graphs without macros/functions? Any ideas?

…Bump?

I can help with one of your issues.

Drag off of the Bind Event On Media Opened, and type in Create Event. You can use this node in functions and possibly macros.

Aesais, thanks for the tip, that indeed seems to solve a part of the problem! (for functions at least; unfortunately the “Bind Event to …” nodes seem to be prohibited in macros)

So, the situtation:

Have a dedicated event: solved
Bind that event to the async op completion signal: solved (for functions)
On signal, get execution back to the initial execution context: unsolved

I’m starting to wonder why some nodes even are prohibited in macros, as macros should fully expand during compilation anyways… This would be just so easy if macros would allow event-related nodes.