Coroutines

This module provides core functionality for working with coroutines in the application. Coroutines can be used to perform asynchronous tasks.

To use this module, include the following line in your project file:

require engine.async.coroutine // or require engine.core

Here is an example of how to use coroutines:

[async] def await_mouse_press() : void {
    // Coroutine that waits for a mouse button press
    while (!mouse_button_pressed(MouseButton Left)) {
        await_next_frame() // Skip frame
    }
}

[async] def smooth_move(node : NodeId; from, to : float3; time : float) : void {
    // Coroutine that moves a node from one position to another over a given time
    var t = 0f
    while (t < time) {
        // Smoothly move the node from one position to another
        node.localPosition = lerp(from, to, float3(t / time))
        await_next_frame()
        t += get_delta_time()
    }

    node.localPosition = to
}

[async] def start_game() : void {
    // Step 1 - wait for mouse press
    await(await_mouse_press())
    // Step 2 - move the cube
    // 'cube' is a NodeId created earlier
    start_coroutine(cube, smooth_move(cube, float3(0, 0, 0), float3(0, 0, 1), 1.))
}

def on_initialize() : void {
    start_coroutine(start_game())
}

Note

return false can be used inside a coroutine to finish it early. Use yield false to yield coroutine execution without completing it.

Warning

Be aware that coroutines can’t be hot reloaded. If you change the coroutine code, you need to restart the application to apply the changes.

Functions

start_coroutine(f: iterator<bool>)

Starts a coroutine with the provided iterator.

Arguments:
  • f : iterator<bool> - the iterator for the coroutine

Usage example:

start_coroutine(start_game())
start_coroutine(node: NodeId; f: iterator<bool>)

Starts a coroutine associated with a specific scene node.

Arguments:
  • node : NodeId - the scene node

  • f : iterator<bool> - the iterator for the coroutine

Usage example:

start_coroutine(myNode, move_node(myNode, 10, 0, 0))
stop_coroutines(node: NodeId): bool

Stops the coroutine associated with the specified scene node.

Arguments:
  • node : NodeId - the ID of the scene node

Returns:
  • bool - true if associated coroutine was found and stopped, false otherwise

Usage example:

stop_coroutine(myNode)
stop_coroutines(): bool

Stops all active and pending coroutines.

Returns:
  • bool - true if any coroutines were stopped, false otherwise

is_coroutine_running(): bool

Checks if there are any active coroutines. Use is_coroutine_running(NodeId()) to check coroutines unassociated with any scene node.

Returns:
  • bool - true if there are active coroutines, false otherwise

Usage example:

if (!is_coroutine_running()) {
    print("There are no active coroutines")
}
is_coroutine_running(node: NodeId): bool

Checks if there is an active coroutine associated with the specified scene node.

Arguments:
  • node : NodeId - the scene node

Returns:
  • bool - true if there is an active coroutine associated with the scene node, false otherwise

Usage example:

if (is_coroutine_running(myNode)) {
    print("There is an active coroutine associated with myNode")
}
await_next_frame()

This function is used to suspend coroutine until next frame.

await(a: iterator<bool>): bool

This function is used to wait for the result of the async function.

Arguments:
  • a : iterator<bool>

await(a: iterator<variant<res:auto(T);wait:bool>>): T

This function is used to wait for the result of the async function.

Arguments:
async_run(a: iterator<auto>): auto

This function runs async function until it is finished.

Arguments:
  • a : iterator<auto>

async_run_all(a: array<iterator<auto>>): auto

This function runs all async function until they are finished (in parallel, starting from the last one).

Arguments:
  • a : array<iterator<auto>>