Async Task Pattern

Overview

All HEGo methods that interact with Houdini Engine run on a background worker thread. Instead of blocking GDScript until the call completes, each method returns an HEGoTask immediately. The task progresses through four states:

PENDING

Waiting in the queue.

RUNNING

Currently executing on the worker thread.

COMPLETED

Finished successfully; result is available.

FAILED

Encountered an error; see get_error_message().

This keeps the Godot editor and game loop responsive while Houdini Engine does its work.

Awaiting a Task

The recommended pattern is a small helper function that polls the task status once per frame:

func _await_task(task: HEGoTask) -> Variant:
    while task.get_status() < HEGoTask.COMPLETED:
        await get_tree().process_frame
    if task.get_status() == HEGoTask.FAILED:
        push_error("Task failed: " + task.get_error_message())
        return null
    return task.get_result()

Every HEGo demo script includes this helper. Use it like this:

# Instantiate an HDA
var asset = HEGoAssetNode.new()
asset.op_name = "Sop/my_hda"
await _await_task(asset.instantiate())

# Set parameters and cook
await _await_task(asset.set_parm("height", 5.0))
await _await_task(asset.cook())

# Fetch output
var surfaces = await _await_task(asset.fetch_surfaces(my_config))

Error Handling

When a task fails, get_status() returns HEGoTask.FAILED and get_error_message() contains the error description. The _await_task helper shown above returns null on failure, so callers can check for that:

var result = await _await_task(asset.cook())
if result == null:
    print("Cook failed, check the error log")
    return

Task Queue Inspection

HEGoAPI exposes methods for inspecting the scheduler state at runtime:

The HEGo bottom panel includes a Tasks column in the HDA tab that displays the live queue and completed task history using these methods.

Task Ordering

Tasks are executed in strict submission order on a single worker thread. When you await each task sequentially, later tasks naturally wait for earlier ones. If you submit multiple tasks without awaiting in between, they queue up and run in order:

# These three tasks queue up and run one after another
var t1 = asset.set_parm("width", 10)
var t2 = asset.set_parm("depth", 20)
var t3 = asset.cook()

# Wait only for the last one -- the earlier ones will have finished by then
await _await_task(t3)