Skip to content

Event System

renanbomtempo edited this page Jul 1, 2026 · 2 revisions

⚠️ This wiki is under construction. Pages are being populated incrementally.

Event System

Events in Nodens follow a data-oriented principle, where an event is a plain-old-data (POD) struct with an appropriate Name member variable for debugging:

struct EventExample {
    static constexpr std::string_view Name = "Example";
    // More Data members...
}

To enforce this we use C++20 concepts:

template <typename TEvent>
concept Event = std::is_standard_layout_v<TEvent> 
                && std::is_trivially_copyable_v<TEvent> 
                && requires { 
                    { TEvent::Name } -> std::same_as<const std::string_view&>;
                };

Nodens separates Events into two categories:

  • Input Events: These are any events coming in from the GLFW, be it input events (e.g. key or button presses) or window events (e.g. close or resize window).
  • Non-input Events: Any other event defined by your application or other subsystems.

Each category is routed through the framework in a different way.

Input Events

All available input event types are defined on src/Nodens/Events/InputEvents.cppm under the Nodens::InputEvents namespace. We use an std::variant named InputEvent to store arbitrary input events, and they are routed through the LayerStack inside a RoutedInputEvent wrapper struct:

struct RoutedInputEvent {
    InputEvent Event;
    bool Handled;
}

The Handled flag is used to mark input events as "consumed" so that they don't propagate further down the layer stack.

All input events generated by the window are immediately passed to the Application::OnInputEvent method, which is set as the GLFW window callback. Traversing the LayerStack from top to bottom, each Layer's own OnInputEvent method is called and the event can be dispatched to their appropriate handlers. The dispatch process can be made using the InputEventDispatcher utility as follows

void YourLayer::OnInputEvent(RoutedInputEvent& e) {
    InputEventDispatcher dispatcher(e);

    dispatcher.Dispatch<Nodens::InputEvents::KeyPressedEvent>(
        [this](Nodens::InputEvents::KeyPressedEvent& event){
            std::print("Handled event {}", event); 
            return true;
        }
    )
}

The templated Dispatch<EventType>(Handler) method calls the Handler function if the type held by the variant e.Event matches the EventType passed as the template parameter.

Non-input Events

Non-input events are routed exclusively through the EventBus using type-erasure techniques.

The Event Bus

The EventBus is a singleton class (for now) that implements a publisher/subscriber model, and features both immediate dispatch (handling events on the local stack) and thread-safe deferred dispatch using double-buffered per-event-type queues.

See Also

  • Layer System: How input events are routed through layers.
  • Event, InputEventDispatcher, EventBus in the API Reference.

Clone this wiki locally