# How to Use ImGui with BGFX and SDL in Equilibrium Engine

> Learn to use ImGui with BGFX and SDL in Equilibrium Engine. This guide explains the ImguiBgfxSdlSystem for seamless integration, initialization, rendering, and input handling.

- Repository: [Alexander/equilibriumengine](https://github.com/clibequilibrium/equilibriumengine)
- Tags: how-to-guide
- Published: 2026-02-27

---

**The Equilibrium Engine integrates Dear ImGui with BGFX and SDL2 through the `ImguiBgfxSdlSystem` ECS system, which handles context initialization, frame rendering, and input event forwarding automatically.**

The Equilibrium Engine uses **flecs** as its Entity Component System (ECS) backbone and binds **Dear ImGui** to the **BGFX** graphics abstraction layer and **SDL2** window system via the *cimgui* C bindings. This architecture allows developers to build immediate-mode GUI overlays without manually managing graphics API specifics or platform window events.

## Architecture of the ImGui Integration

The integration is encapsulated in the **ImguiBgfxSdlSystem**, which registers three lifecycle callbacks as ECS observers. This system abstracts the complexity of wiring ImGui to BGFX and SDL2 while exposing a simple component-based API for user-defined UI modules.

### The ImguiBgfxSdlSystem Lifecycle

The system provides three core callbacks that manage the ImGui context from startup to shutdown:

- **`ImguiInitialize`** (`imgui_bgfx_sdl_system.c:L70-L102`): Creates an `ImGuiContext`, configures ImGui flags for keyboard navigation, docking, and multi-viewport support, loads the default font, and initializes both the BGFX and SDL backends.
- **`ImguiUpdate`** (`imgui_bgfx_sdl_system.c:L127-L162`): Starts a new ImGui frame, executes every registered `GuiSystem` (user-defined UI modules), renders the ImGui draw data through BGFX, and updates platform windows.
- **`ImguiShutdown`** (`imgui_bgfx_sdl_system.c:L166-L171`): Shuts down both ImGui backends and logs the cleanup.

### Component Definitions

The engine defines GUI-related components in [`equilibrium/components/gui.h`](https://github.com/clibequilibrium/equilibriumengine/blob/main/equilibrium/components/gui.h) (`L8-L14`):

```c
typedef struct GuiSystem {
    UpdateCallback Update;   // User-defined UI logic
} GuiSystem;

typedef struct GuiContext {
    void *value;             // Stores the ImGuiContext pointer
} GuiContext;

```

The `GuiSystem` component acts as the extension point for custom UI code, while `GuiContext` stores the underlying ImGui context pointer for internal use.

### Backend Wiring and Initialization

The system initializes platform-specific backends during the `ImguiInitialize` phase. In `imgui_bgfx_sdl_system.c:L98-L108`, the engine calls:

```c
// BGFX backend initialization (view-id 255 reserved for ImGui)
ImGui_Implbgfx_Init(255);

// SDL2 backend initialization (platform-specific variant)
ImGui_ImplSDL2_InitForMetal(window);  // Or InitForD3D, InitForOpenGL

```

The BGFX renderer implementation resides in [`3rdparty/cimgui/imgui_impl_bgfx.h/.cpp`](https://github.com/clibequilibrium/equilibriumengine/blob/main/3rdparty/cimgui/imgui_impl_bgfx.h/.cpp), while the SDL2 input backend is located in [`3rdparty/cimgui/imgui_impl_sdl.h`](https://github.com/clibequilibrium/equilibriumengine/blob/main/3rdparty/cimgui/imgui_impl_sdl.h). The initialization automatically configures multi-viewport support and applies a dark theme via `ApplyImGuiDarkStyle`.

### Automatic Event Forwarding

The engine wires SDL2 input events directly to ImGui without manual intervention. In `imgui_bgfx_sdl_system.c:L111-L113`, the system sets the input callback:

```c
input->callback = ImGui_ImplSDL2_ProcessEvent;

```

This ensures that every SDL event (mouse, keyboard, window) is automatically processed by ImGui before application systems handle them.

## Step-by-Step Implementation

To add custom ImGui interfaces to your Equilibrium Engine project, you register the system once and then create entities with `GuiSystem` components.

### 1. Register the ImGui System

Call `ImguiBgfxSdlSystemImport` during engine startup, typically in your launcher or [`main.c`](https://github.com/clibequilibrium/equilibriumengine/blob/main/main.c) after initializing the flecs world:

```c
// launcher/launcher.cc or your bootstrap file
world_t *world = ecs_init();
ImguiBgfxSdlSystemImport(world);   // Registers ImGui + BGFX + SDL integration

```

This function (`imgui_bgfx_sdl_system.c:L173-L188`) registers the three lifecycle callbacks and imports the necessary component modules.

### 2. Define a Custom UI System

Create a component that implements the `GuiSystem.Update` callback. The engine handles `igNewFrame` and `igRender` automatically—you only write the widget logic:

```c
// my_ui_system.c
#include "cimgui.h"
#include "equilibrium/components/gui.h"

static void MyUIUpdate(ecs_iter_t *it) {
    // ImGui frame already begun by ImguiUpdate
    igBegin("Demo Window", NULL, 0);
    
    if (igButton("Press me!", (ImVec2){0,0})) {
        ecs_trace("Button pressed!");
    }
    
    igEnd();
}

void RegisterMyUISystem(world_t *world) {
    ecs_entity_t ui = ecs_new_id(world);
    ecs_set(world, ui, GuiSystem, { .Update = MyUIUpdate });
}

```

Place this registration after importing the ImGui system:

```c
// After ImguiBgfxSdlSystemImport(world)
RegisterMyUISystem(world);

```

### 3. Customizing ImGui Style (Optional)

The engine applies a dark style automatically during initialization. To override this, access the style struct after system import:

```c
void SetCustomStyle(void) {
    ImGuiStyle *style = igGetStyle();
    style->WindowRounding = 6.0f;
    style->Colors[ImGuiCol_WindowBg] = (ImVec4){0.1f, 0.1f, 0.1f, 1.0f};
}

```

Call your custom style function immediately after `ImguiBgfxSdlSystemImport(world)`.

## Key Source Files

Understanding the file structure helps when debugging or extending the integration:

- **[`equilibrium/components/gui.h`](https://github.com/clibequilibrium/equilibriumengine/blob/main/equilibrium/components/gui.h)**: Declares `GuiSystem`, `GuiContext`, and update callback signatures.
- **[`equilibrium/systems/imgui/imgui_bgfx_sdl_system.c`](https://github.com/clibequilibrium/equilibriumengine/blob/main/equilibrium/systems/imgui/imgui_bgfx_sdl_system.c)**: Implements initialization (`L70-L102`), update loop (`L127-L162`), and shutdown (`L166-L171`).
- **[`3rdparty/cimgui/imgui_impl_bgfx.h/.cpp`](https://github.com/clibequilibrium/equilibriumengine/blob/main/3rdparty/cimgui/imgui_impl_bgfx.h/.cpp)**: BGFX renderer backend for ImGui draw list submission.
- **[`3rdparty/cimgui/imgui_impl_sdl.h`](https://github.com/clibequilibrium/equilibriumengine/blob/main/3rdparty/cimgui/imgui_impl_sdl.h)**: SDL2 event handling and window management backend.
- **[`editor/systems/imgui_overlay_system.c`](https://github.com/clibequilibrium/equilibriumengine/blob/main/editor/systems/imgui_overlay_system.c)**: Reference implementation showing production usage of `GuiSystem`.

## Summary

- **Register once**: Call `ImguiBgfxSdlSystemImport(world)` during engine startup to initialize the BGFX and SDL2 backends automatically.
- **Extend via components**: Implement `GuiSystem.Update` callbacks to draw UI; the engine manages frame lifecycle and rendering.
- **Event handling is automatic**: SDL2 events are forwarded to ImGui via `ImGui_ImplSDL2_ProcessEvent` without manual wiring.
- **Multi-viewport support**: The system initializes ImGui with docking and multi-viewport flags enabled by default.
- **View ID 255**: BGFX reserves view ID 255 for ImGui rendering, ensuring it draws on top of the main scene.

## Frequently Asked Questions

### How do I initialize ImGui in Equilibrium Engine?

Import the `ImguiBgfxSdlSystem` module by calling `ImguiBgfxSdlSystemImport(world)` after `ecs_init()`. This single call registers the initialization, update, and shutdown callbacks that wire ImGui to BGFX and SDL2, as implemented in `imgui_bgfx_sdl_system.c:L173-L188`.

### Do I need to call igNewFrame or igRender manually?

No. The `ImguiUpdate` system callback (`imgui_bgfx_sdl_system.c:L127-L162`) calls `igNewFrame` before executing your `GuiSystem.Update` callbacks and calls `igRender` followed by `ImGui_Implbgfx_RenderDrawLists` afterward. Your UI code only needs to contain ImGui drawing commands between `igBegin` and `igEnd`.

### Which graphics APIs are supported?

The integration supports any renderer BGFX supports (Direct3D, Metal, OpenGL, Vulkan) because it uses BGFX's view system for rendering. The SDL2 backend initialization selects the appropriate platform-specific function (e.g., `ImGui_ImplSDL2_InitForMetal`, `InitForD3D`, or `InitForOpenGL`) based on the target platform during `ImguiInitialize`.

### How do I disable docking or multi-viewport features?

Modify the ImGui configuration flags in `imgui_bgfx_sdl_system.c:L70-L102` within the `ImguiInitialize` function. Look for the lines setting `ImGuiConfigFlags_DockingEnable` and `ImGuiConfigFlags_ViewportsEnable`, and remove or comment out the flags you do not need before the context is bound.