# Event System Source: `src/dusk/event/` ## Overview The event system is a simple publish-subscribe mechanism backed by caller-owned static arrays. There is no heap allocation in the event system itself -- the caller provides the backing storage. ## API ```c typedef void (*eventcallback_t)(void *params, void *user); typedef struct { eventcallback_t *callbacks; void **users; size_t size; uint32_t count; } event_t; ``` ### Initialise ```c void eventInit( event_t *event, eventcallback_t *callbacks, void **users, size_t size ); ``` `callbacks` and `users` are caller-owned arrays of length `size`. Both are zeroed by `eventInit`. `users` may be `NULL` if no subscriber needs a user pointer. ### Subscribe / unsubscribe ```c void eventSubscribe(event_t *event, eventcallback_t callback, void *user); void eventUnsubscribe(event_t *event, eventcallback_t callback); ``` The same `(callback, user)` pair may only be subscribed once -- `eventSubscribe` asserts on a duplicate. `eventUnsubscribe` is a no-op if the pair is not found. Unsubscribing uses swap-with-last to keep the array packed; ordering is not preserved. ### Fire ```c void eventInvoke(const event_t *event, void *params); ``` Calls every subscriber in registration order, passing `params` and each subscriber's `user` pointer. ## Usage pattern Declare the backing arrays alongside the event struct, typically as struct fields or static variables: ```c #define MY_EVENT_CAPACITY 4 typedef struct { event_t onComplete; eventcallback_t _completeCbs[MY_EVENT_CAPACITY]; void *_completeUsers[MY_EVENT_CAPACITY]; } mystate_t; // Init: eventInit( &state.onComplete, state._completeCbs, state._completeUsers, MY_EVENT_CAPACITY ); // Publish: eventInvoke(&state.onComplete, &someParams); // Subscribe from outside: eventSubscribe(&state.onComplete, myHandler, myUserPtr); ``` ## Constraints - Capacity is fixed at init time. Exceeding it is a runtime assertion. - Subscriber order is not stable after an unsubscribe. - `eventInvoke` is synchronous -- all callbacks run on the calling thread before it returns. - Do not subscribe or unsubscribe from inside a callback -- the array may shift during iteration. ## Where events are used | Subsystem | Event | Fires when | |-----------|-------|-----------| | `inputactiondata_t` | `onPressed`, `onReleased` | Action button state changes | | `uitextbox_t` | `onPageComplete` | Typewriter scroll reveals the full page | | `uitextbox_t` | `onLastPage` | Last page is fully scrolled | | `uifullbox_t` | `onTransitionEnd` | Colour transition animation completes | | `uiloading_t` | `onShow` / `onHide` | Loading indicator fade completes | | Asset system | `assetbatch_t` callback | All entries in a batch reach LOADED/ERROR | See `.claude/ui.md` for the UI event details.